Linux应用编程之串口操作20170901
主要介绍在Linux应用程序下对串口的操作:
1.串口初始化
int InitCom()
{
int Ret;
Ret = SerailComm.OpenCom( ComPortDevPath, 0 );
if( Ret < 0 )
{
return Ret;
}
if(SerailComm.SetComSpeed( ComBaudRate ) < 0 )
{
SerailComm.CloseCom();
return Ret;
}
if(SerailComm.SetComParity(8, 1, 'N', 0, 0) < 0)
{
SerailComm.CloseCom();
return Ret;
}
Ret = SerailComm.SetComRawMode();
if( Ret < 0 )
{
SerailComm.CloseCom();
return Ret;
}
if( SerailComm.SetComSelectTimeOut(1, 0, READ_TIMEOUT_F) < 0 )
{
CloseCom();
return Ret;
}
if( SerailComm.SetComSelectTimeOut( 0, 500000, WRITE_TIMEOUT_F) < 0 )
{
SerailComm.CloseCom();
return Ret;
}
SerailComm.SetSerialCommBlock( 0 );
return 0;
}
2.读数据
int ReadCom()
{
char cRecvBuf[256];
int iBufSize = 256;
memset(cRecvBuf, 0, sizeof(cRecvBuf));
return SerailComm.ReadBinCom(cRecvBuf, iBufSize))
}
3.写数据
int WriteCom(u8 *WriteBuf, int Size)
{
return SerailComm.WriteBinCom((char*)WriteBuf, Size);
}
4.关闭串口
void CloseCom()
{
SerailComm.CloseCom();
}
5.附:上述使用到的串口类
#include "ComTransmit.h"
#include <assert.h>
#include <unistd.h>
#include <termios.h>
#include <ctype.h>
#include <errno.h> #include "tracelevel.h"
#include "MdvrModulCom.h" extern HANDLE_DVR g_hDvr; pthread_mutex_t ComCommutex = PTHREAD_MUTEX_INITIALIZER; //pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; speedPara speed_atr[] =
{
{B300,},
{B600,},
{B1200,},
{B2400,},
{B4800,},
{B9600,},
{B19200,},
{B38400,},
{B57600,},
{B115200,} ,
{B230400,}
}; CComTransmit::CComTransmit():m_fp(NULL),m_fd(-)
{
memset(&Rtimeout,,sizeof(Rtimeout));
memset(&Wtimeout,,sizeof(Wtimeout));
m_binit = ;
} CComTransmit::~CComTransmit()
{ } int CComTransmit::OpenCom(const char * deviceName, int isMutex)
{
assert(deviceName != NULL); if(m_binit == )
return ; m_fd = open(deviceName,O_RDWR);
if(m_fd < )
{
printf("Open Com [%s] failure! %s\n",deviceName, strerror(errno));
return -;
} printf("Open Com [%s] Sucess\n",deviceName); m_fp = fdopen(m_fd, "r+b");
if(m_fp == NULL)
{
return -;
} m_binit = ;
m_mutex_flag = isMutex; return ;
} void CComTransmit::CloseCom()
{
int ret = close(m_fd);
if(ret < )
{
printf("close Com failure!\n");
}
m_fp = NULL;
m_binit = ;
} int CComTransmit::SetComSpeed(unsigned int speed)
{
int comspeed = ;
int status = ;
struct termios Opt;
int ret = -; for(unsigned int i = ;i < sizeof(speed_atr)/sizeof(speedPara);i++)
{
if(speed == speed_atr[i].userSpeed)
{
comspeed = speed_atr[i].sysSpeed;
break;
}
} if(!comspeed)
{
assert(comspeed != );
} if(m_fd < )
{
return -;
}
tcgetattr(m_fd, &Opt);
tcflush(m_fd, TCIOFLUSH);
ret = cfsetispeed(&Opt, comspeed);
if(ret < )
{
perror("set input speed error!\n");
return -;
} ret = cfsetospeed(&Opt, comspeed);
if(ret < )
{
perror("set output speed error!\n");
return -;
} status = tcsetattr(m_fd, TCSANOW, &Opt);
if(status != )
{
perror("tcsetattr fd1");
return -;
} tcflush(m_fd,TCIOFLUSH);
return ;
} int CComTransmit::SetComParity(int databits, int stopbits, int parity,int flowctrl, int Rs485)
{
struct termios options; if(m_fd < )
{
return -;
} if ( tcgetattr( m_fd,&options) != )
{
printf("SetComParity 1");
return-;
} options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case :
options.c_cflag |= CS5;
break;
case :
options.c_cflag |= CS6;
break;
case :
options.c_cflag |= CS7;
break;
case :
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return -;
}
switch (parity)
{
case 'n':
case 'N':
case :
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
case :
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
case :
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return -;
} /* 设置停止位*/
switch (stopbits)
{
case :
options.c_cflag &= ~CSTOPB;
break;
case :
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (-);
} switch(flowctrl) /* 设置流控制*/
{
case :
options.c_cflag &= ~CRTSCTS; /*no flow control*/
break;
case :
options.c_cflag |= CRTSCTS; /*hardware flow control*/
break;
case :
options.c_cflag |= IXON|IXOFF|IXANY; /*software flow control*/
break;
default:
options.c_cflag &= ~CRTSCTS; /*no flow control*/
break;
}
#if 0
if(Rs485)
{
options.c_cflag |= (0x00000001<<);
}
else
{
options.c_cflag &= (~(0x00000001<<));
}
#else PRODUCT_INFO_ST productInfo; EX_GetProductInfo(g_hDvr, &productInfo);
if((productInfo.productTypeID == MDVR_JH6S8_720P)||(productInfo.productTypeID == MDVR_JH6S4_720P))
{
if(Rs485)
{
options.c_cflag |= (0x00000001<<);
}
else
{
options.c_cflag &= (~(0x00000001<<));
} }
#endif
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK; options.c_cc[VTIME] = ; // 1 seconds
options.c_cc[VMIN] = ; tcflush(m_fd,TCIFLUSH); /* Update the options and do it NOW */
if (tcsetattr(m_fd,TCSANOW,&options) != )
{
perror("SetComParity 2");
return (-);
} return ();
} //0---read ,1--write
int CComTransmit::SetComSelectTimeOut(int sec,int usec,SELECT_TIMEOUT_F rwflag)
{
if(rwflag == WRITE_TIMEOUT_F)
{
Wtimeout.tv_sec = sec;
Wtimeout.tv_usec = usec;
}
else
{
Rtimeout.tv_sec = sec;
Rtimeout.tv_usec = usec;
} return ;
} int CComTransmit::IOFlush()
{
tcflush(m_fd, TCIOFLUSH);
return ;
} int CComTransmit::SetComRawModeEx()
{
int ret = ;
struct termios options; tcgetattr(m_fd, &options); tcflush(m_fd, TCIOFLUSH);
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSTOPB;
options.c_oflag &= ~OPOST; #if 0
printf("before iflag %x, lflag %x, oflag %x \n", options.c_iflag, options.c_lflag, options.c_oflag); // options.c_lflag = 0 ;
// options.c_oflag = 0 ;
// options.c_iflag = 0;
options.c_lflag &= ~(ICANON |ISIG);
options.c_iflag &= ~(ICRNL|IGNCR); //options.c_iflag |= (IGNBRK|BRKINT);
options.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); printf("iflag %x, lflag %x, oflag %x \n", options.c_iflag, options.c_lflag, options.c_oflag); #endif //|PARMRK|ISTRIP|IGNCR|ICRNL|IXON|INLCR
tcflush(m_fd, TCIFLUSH);
options.c_cc[VTIME] = ; //128;
options.c_cc[VMIN] = ;// 1; cfmakeraw(&options); ret = tcsetattr(m_fd,TCSANOW,&options);
if (ret < )
{
perror("set raw mode error!");
return ret;
} return ;
} int CComTransmit::SetComRawMode()
{
int ret = ;
struct termios options; tcgetattr(m_fd, &options); cfmakeraw(&options);
ret = tcsetattr(m_fd,TCSANOW,&options);
if (ret < )
{
perror("set raw mode error!");
} return ret;
} int CComTransmit::ReadCom(char *ReadBuffer,int size,int *retSize)
{
int retval = -; fd_set serial;
struct timeval rdtimeout;
*retSize = ;
if(m_fd < )
{
fprintf(stderr,"%s[%d]:serial have not open!\n",__FILE__,__LINE__);
return -;
} FD_ZERO(&serial);
FD_SET(m_fd, &serial);
rdtimeout = Rtimeout;
#if 1 do{
retval = select(m_fd+, &serial, NULL, NULL, &rdtimeout);
if(retval < )
{
if(errno == EINTR)
{
//printf("select Interruppter!\n");
}
else
{
break;
}
}
}while(retval == -); if(retval <= )
{
return -;
} //读数据写BUFFER
if(FD_ISSET(m_fd, &serial)!=)
{
if(NULL != m_fp)
{
if(m_mutex_flag)
{
pthread_mutex_lock(&ComCommutex);
fgets(ReadBuffer, size, m_fp);
pthread_mutex_unlock(&ComCommutex);
}
else
{
fgets(ReadBuffer, size, m_fp);
}
*retSize = strlen(ReadBuffer);
}
}
return ;
#else
if(m_fd > )
{
retval = read(m_fd, ReadBuffer, size);
} if(retval > )
{
*retSize = retval;
}
else
{
*retSize = ;
} return retval; #endif
} int CComTransmit::ReadComEx( char *ReadBuffer,int size,int *retSize )
{
fd_set read_fds;
int retval;
struct timeval rdtimeout; rdtimeout.tv_sec = Rtimeout.tv_sec;
rdtimeout.tv_usec = Rtimeout.tv_usec; if(m_fd < )
{
fprintf(stderr,"%s[%d]:serial have not open!\n",__FILE__,__LINE__);
return -;
} FD_ZERO(&read_fds);
FD_SET(m_fd, &read_fds); retval = select(m_fd + , &read_fds, NULL, NULL, &rdtimeout);
if( retval <= )
{
return -;
} if ( !FD_ISSET(m_fd, &read_fds) )
{
//printf("Serail Com[%s] read time out[%d]\n", m_SerialPath, time_out);
return -;
} retval = read(m_fd, ReadBuffer, size);
*retSize = retval; if(*retSize < )
{
return -;
} return ;
} /*
*函数功能:读取串口binary数据
*创建作者:freeman on 2010/0818
*/
int CComTransmit::ReadBinCom(char *ReadBuffer,int size)
{
int retval = -; #if 0 fd_set serial;
struct timeval rdtimeout; if(m_fd < )
{
fprintf(stderr,"%s[%d]:serial have not open!\n",__FILE__,__LINE__);
return -;
} FD_ZERO(&serial);
FD_SET(m_fd, &serial);
rdtimeout = Rtimeout; do{
retval = select(m_fd+, &serial, NULL, NULL, &rdtimeout);
if(retval < )
{
if(errno == EINTR)
{
//printf("select Interruppter!\n");
}
else
{
break;
}
}
}while(retval == -); if(retval <= )
{
return -;
} //读数据写BUFFER
if(FD_ISSET(m_fd,&serial)!=)
{
if(NULL != m_fp)
{
return read(m_fd,ReadBuffer,size);
}
}
return ; #else if(m_fd > )
{
retval = read(m_fd, ReadBuffer, size);
}
else
{
TRACE_NET(ERR,"ReadBinCom ERR:%d\n",m_fd);
}
return retval; #endif
} int CComTransmit::WriteCom(char *WriteBuffer,int size)
{
int ret = -;
#if 1
fd_set serial;
int retval =;
struct timeval WTtimeout; if(m_fd < )
{
TRACE_NET(ERR, "---serial have not open!\n");
return -;
} // printf("Snd Com %s \n", WriteBuffer); FD_ZERO(&serial);
FD_SET(m_fd, &serial);
WTtimeout = Wtimeout;
if ((retval = select(m_fd+, NULL, &serial, NULL, &WTtimeout)) < )
{
TRACE_NET(ERR, "select error! ---- \n");
return -;
} if(retval == )
{
TRACE_NET(ERR, "select timeout! ---- \n");
return -;
} //读数据写BUFFER
if(FD_ISSET(m_fd,&serial)!=)
{
pthread_mutex_lock(&ComCommutex);
ret = write(m_fd, WriteBuffer ,size);
pthread_mutex_unlock(&ComCommutex); if(ret == -)
{
TRACE_NET(ERR, "serial send data failed -----!\n");
return -;
}
} return ret;
#else
ret = write(m_fd, WriteBuffer ,size);
// printf("Send cmd %d \n", ret);
if(ret == -)
{
printf("serial send data failed -----error!\n");
return -;
}
return ret; #endif
} int CComTransmit::WriteBinCom(char *WriteBuffer,int size)
{
int ret = -;
#if 0
fd_set serial;
int retval =;
struct timeval WTtimeout; if(m_fd < )
{
fprintf(stderr,"%s:%d---serial have not open!\n", __FILE__, __LINE__);
return -;
} // printf("Snd Com %s \n", WriteBuffer); FD_ZERO(&serial);
FD_SET(m_fd, &serial);
WTtimeout = Wtimeout;
if ((retval = select(m_fd+, NULL, &serial, NULL, &WTtimeout)) < )
{
fprintf(stderr,"%s[%d]:select error!---------------\n",__FILE__,__LINE__);
return -;
} if(retval == )
{
fprintf(stderr,"%s[%d]:select timeout!---------------\n",__FILE__,__LINE__);
return -;
} //读数据写BUFFER
if(FD_ISSET(m_fd,&serial)!=)
{
pthread_mutex_lock(&Commutex);
ret = write(m_fd, WriteBuffer ,size);
pthread_mutex_unlock(&Commutex); if(ret == -)
{
printf("serial send data failed -----error!\n");
return -;
}
} return ret;
#else
if(m_fd > )
ret = write(m_fd, WriteBuffer ,size);
// printf("Send cmd %d \n", ret);
if(ret == -)
{
TRACE_NET(ERR, "serial send data failed -----!\n");
return -;
} return ret;
#endif
} int CComTransmit::GetPortFD()
{
return m_fd;
} FILE* CComTransmit::GetPortFP()
{
return m_fp;
} void CComTransmit::SetSerialCommBlock(int isBlock)
{
int nFlags = fcntl(m_fd, F_GETFL, ); if(isBlock)
{
fcntl(m_fd, F_SETFL, );
}
else
{
fcntl(m_fd, F_SETFL, nFlags|O_NONBLOCK);
}
} int CComTransmit::ReadComWithBuf(char *ReadBuffer,int size,int *retSize)
{
fd_set serial;
int retval;
struct timeval rdtimeout;
*retSize = ;
int left = ;
int recvlen = ; if(m_fd < )
{
fprintf(stderr,"%s[%d]:serial have not open!\n",__FILE__,__LINE__);
return -;
} for(int i = ;i < size - && i < m_len;i++)
{
ReadBuffer[i] = m_buf[i];
if(m_buf[i] == '\n')
{
ReadBuffer[i+] = ;
memmove(m_buf,&m_buf[i+],m_len-(i+));
m_len -= (i+);
*retSize = i+;
return *retSize;
}
} FD_ZERO(&serial);
FD_SET(m_fd, &serial);
rdtimeout = Rtimeout; do{
retval = select(m_fd+, &serial, NULL, NULL, &rdtimeout);
if(retval < )
{
if(errno == EINTR)
{
//printf("select Interruppter!\n");
}
else
{
break;
}
}
}while(retval == -); if(retval <= )
{
return -;
} //读数据写BUFFER
if(FD_ISSET(m_fd,&serial)!=)
{
if(NULL != m_fp)
{
left = SERIAL_BUF_LEN - m_len;
if(left > )
{
recvlen = read(m_fd,&m_buf[m_len],left);
if(recvlen > )
{
m_len += recvlen;
}
}
else
{
// WRITE_DBG_LOG("串口接收数据512字节内没有换行符号");
m_buf[m_len-] = ;
// WRITE_DBG_LOG("%s",m_buf);
m_len = ;
left = SERIAL_BUF_LEN;
recvlen = read(m_fd,&m_buf[m_len],left);
if(recvlen > )
{
m_len += recvlen;
}
} for(int i = ;i < size - && i < m_len;i++)
{
ReadBuffer[i] = m_buf[i];
if(m_buf[i] == '\n')
{
ReadBuffer[i+] = ;
memmove(m_buf,&m_buf[i+],m_len-(i+));
m_len -= (i+);
*retSize = i+;
return *retSize;
}
}
}
} return -;
}
CComTransmit.cpp
#ifndef _COM_TRANSMIT_H_
#define _COM_TRANSMIT_H_ #include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h> #define SERIAL_BUF_LEN 512 typedef struct {
unsigned long baudrate; /*波特率*/
unsigned char databit; /*数据位,取值5、6、7、8*/
unsigned char parity; /*奇偶校验位,取值'n':无校验'o':奇校验'e'偶校验*/
unsigned char stopbit; /*停止位,取值1,2*/
unsigned char reserve; /*保留字节*/
}Terminal; typedef struct
{
int sysSpeed;
unsigned long userSpeed;
}speedPara; typedef enum
{
READ_TIMEOUT_F = ,
WRITE_TIMEOUT_F
}SELECT_TIMEOUT_F; class CComTransmit
{
private:
//
FILE *m_fp;
int m_fd;
int m_mutex_flag;
struct timeval Rtimeout;
struct timeval Wtimeout;
int m_binit;
char m_buf[SERIAL_BUF_LEN];
int m_len; public:
//
CComTransmit();
~CComTransmit();
int OpenCom(const char *deviceName, int isMutex = );
void CloseCom();
int SetComSpeed(unsigned int speed);
int SetComParity(int databits, int stopbits, int parity,int flowctrl, int Rs485);
int SetComRawMode();
int SetComRawModeEx();
int SetComSelectTimeOut(int sec,int usec,SELECT_TIMEOUT_F RWflag);//0--read,1--wirte
int IOFlush();
int ReadCom(char *ReadBuffer,int size,int *retSize);
int ReadComEx( char *ReadBuffer,int size,int *retSize );
int ReadBinCom(char *ReadBuffer,int size);
int WriteCom(char *WriteBuffer,int size);
int WriteBinCom(char *WriteBuffer,int size); int GetPortFD();
FILE* GetPortFP();
void SetSerialCommBlock(int isBlock);
int ReadComWithBuf(char *ReadBuffer,int size,int *retSize); protected:
//
}; #endif//_COM_TRANSMIT_H_
CComTransmit.h
Linux应用编程之串口操作20170901的更多相关文章
- Linux系统编程--文件IO操作
Linux思想即,Linux系统下一切皆文件. 一.对文件操作的几个函数 1.打开文件open函数 int open(const char *path, int oflags); int open(c ...
- Linux系统编程—信号集操作函数
先来回顾一下未决信号集是怎么回事. 信号从产生到抵达目的地,叫作信号递达.而信号从产生到递达的中间状态,叫作信号的未决状态.产生未决状态的原因有可能是信号受到阻塞了,也就是信号屏蔽字(或称阻塞信号集, ...
- linux下怎样对串口编程
Linux操作系统从一開始就对串行口提供了非常好的支持,本文就Linux下的串行口通讯编程进行简单的介绍. 串口简单介绍串行口是计算机一种经常使用的接口.具有连接线少.通讯简单.得到广泛的使用. 经常 ...
- Linux C 程序 文件操作(Linux系统编程)(14)
文件操作(Linux系统编程) 创建一个目录时,系统会自动创建两个目录.和.. C语言实现权限控制函数 #include<stdio.h> #include<stdlib.h> ...
- MATLAB串口操作和GUI编程
程序说明 V1.0 2015/2/08 MATLAB串口操作和GUI编程 概述 本文介绍了程序AD9512_Serial_GUI的编程思路和功能.该程序设计到MATLAB的图像用户界面编程的基 ...
- Linux下串口操作之数据拼接
串口操作中,特别以非阻塞的方式读取和发送数据,做好进程之间的同步很重要.有时我们会发现这样一个问题,在进行read操作时,一次read不能获得一个完整的数据帧,这就好比你买了一个电脑,送货的先把显示器 ...
- linux下编程epoll实现将GPS定位信息上报到服务器
操作系统:CentOS 开发板:fl2440 开发模块:A7(GPS/GPRS),RT3070(无线网卡) ********************************************** ...
- Linux CGI编程基础【整理】
Linux CGI编程基础 1.为什么使用CGI? 如前面所见,任何的HTML均是静态网页,它无法实现一些复杂的功能,而CGI可以为我们实现.如:a.列出服务器上某个目录中的文件,对目录中的文件进行操 ...
- linux与开发板串口通信
研究了一天的linux串口,结果改了树莓派的系统配置文件config.txt给改了导致系统崩溃....其实我感觉网上的大多数方法都是不符合新版本树莓派的,网上的方法是通过修改系统配置文件后安装mini ...
随机推荐
- NO.06--聊一聊“币”吧!
近期博主更新的频率明显慢来 ,一来是最近的工作比较忙碌,几个项目几乎同时要上线.二来是在思考是不是把我平时生活中的一些事情写进来博客,不只是分享分享技术. 趁着区块链.比特币火爆,博主也算是略有涉猎, ...
- Vue 编程之路(一)——父子组件之间的数据传递
最近公司的一个项目中使用 Vue 2.0 + element UI 实现一个后台管理系统的前端部分,属于商城类型.其中部分页面是数据管理页,所以有很多可以复用的表格,故引入自定义组件.在这里分享一下开 ...
- 【springmvc+mybatis项目实战】杰信商贸-6.重点知识回顾
1.重点知识回顾 Maven1)覆盖仓库文件,实际企业开发,公司会架一个测试服务器,在测试服务器中架私服.我们开发人员的程序,都连接私服.当本地没有项目中要使用的jar,Myeclipse maven ...
- Windows下遍历某目录下的文件
需求:要求遍历某个目录下的所有文件,文件夹 之前遇到过一些参考程序,其中有一种方法只能遍历 FAT32 格式的目录, 无法遍历NTFS的目录.
- 日本IT行业劳动力缺口达22万 在日中国留学生迎来就业好时机 2017/07/18 11:25:09
作者:倪亚敏 来源:日本新华侨报 发布时间:2017/07/18 11:25:09 据日本政府提供的数据,日本2018年应届毕业生的“求人倍率”已经达到了1.78倍.换言之,就是100名大学生 ...
- 亚马逊拟斥资15亿美元建航空货运中心 - Amazon to spend $1.49 bln on air cargo hub, fans talk of bigger ambitions - ReutersFebruary 1, 2017
2月1日消息,亚马逊本周二宣布将在肯塔基州开建其第一个航空货运中心,以应对高速增长的航空货运需求.亚马逊预计,该项目将带来2000个工作岗位. 据悉,该项计划总投入约为15亿美元,亚马逊或可从当地政府 ...
- centos7.2 apache开启.htaccess
打开httpd.conf(在那里? APACHE目录的CONF目录里面),用文本编纂器打开后,查找 (1) AllowOverride None 改为 AllowOverride All (2)去掉下 ...
- eclipse安装反编译器jad
1.下载net.sf.jadclipse_3.3.0.jar.jadclipse_3.3.0.jar.jad.exe 2.将net.sf.jadclipse_3.3.0.jar放在eclipse的安装 ...
- ES6的新特性(9)——对象的扩展
对象的扩展 属性的简洁表示法 ES6 允许直接写入变量和函数,作为对象的属性和方法.这样的书写更加简洁. const foo = 'bar'; const baz = {foo}; baz // {f ...
- Python中用字符串导入module
在Python中,无法通过字符串来导入一个module文件: import "string" # Error x = "string" import x # 不 ...