python和C语言混合编程实例
最近为了测试网速情况怎么样,由于部分业务服务器需要关闭icmp,这样的话采用普通的ping就无法适应我的需求,于是自己简单的写了一个基于tcp端口的ping的程序,由于c执行效率比较的不错,但是开发效率低下,而python是开发效率高,但是执行效率不如C,由于需要大规模的使用,于是用C实现核心部分的代码,并把这部分实现成一个python的模块,由python调用c的模块,下面就贴代码吧
/*tcpportping.c*/
#include<Python.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<sys/time.h>
/*counttimefunctions*/
staticdoublemytime(void)
{
structtimevaltv;
if(gettimeofday(&tv,NULL)==-1)
return0.0;
return(double)tv.tv_usec+(double)tv.tv_sec*1000000;
}
staticPyObject* /*returnsobject*/
tcpping(PyObject*self,PyObject*args)
{
struct sockaddr_inaddr;
struct hostent*hp;
double time;
char *host=NULL;
int fd;
int port,timeout;
if(!PyArg_ParseTuple(args,"sii",&host,&port,&timeout)) /*convertPython->C*/
returnNULL; /*null=raiseexception*/
if((fd=socket(AF_INET,SOCK_STREAM,0))<0){
returnPy_BuildValue("d",-1.0); /*convertC->Python*/
}
bzero((char*)&addr,sizeof(addr));
if((hp=gethostbyname(host))==NULL){
returnPy_BuildValue("d",-2.0); /*convertC->Python*/
}
bcopy(hp->h_addr,&addr.sin_addr,hp->h_length);
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
structtimevaltv;
tv.tv_sec=0;
tv.tv_usec=timeout*1000;
doublestime=mytime();
if(connect(fd,(structsockaddr*)&addr,sizeof(addr))<0){
returnPy_BuildValue("d",-3.0); /*convertC->Python*/
}
fd_setread,write;
FD_ZERO(&read);
FD_ZERO(&write);
FD_SET(fd,&read);
FD_SET(fd,&write);
if(select(fd+1,&read,&write,NULL,&tv)==0){
close(fd);
returnPy_BuildValue("d",-4.0); /*convertC->Python*/
}
doubleetime=mytime();
time=etime-stime;
if(!FD_ISSET(fd,&read)&&!FD_ISSET(fd,&write)){
close(fd);
returnPy_BuildValue("d",-4.0); /*convertC->Python*/
}
close(fd);
returnPy_BuildValue("d",time/1000); /*convertC->Python*/
}
/*registrationtable */
staticstructPyMethodDefportping_methods[]={
{"tcpping",tcpping,METH_VARARGS}, /*methodname,Cfuncptr,always-tuple*/
{NULL,NULL} /*endoftablemarker*/
};
/*moduleinitializer*/
voidinittcpportping() /*calledonfirstimport*/
{ /*namemattersifloadeddynamically*/
(void)Py_InitModule("tcpportping",portping_methods); /*modname,tableptr*/
}
编译成python模块
gcctcpportping.c -I/usr/include/python2.4-shared-L/usr/bin-fpic-lpython2.4-otcpportping.so
下面是python调用c模块的代码:
#!/usr/bin/envpython
importtcpportping
importtime
i=0
whilei<5:
t=tcpportping.tcpping('www.baidu.com',80,1000)
ift<0:
print"timeout"
else:
printt
time.sleep(0.5)
i+=1执行python代码就可以实现端口ping的结果,从测试的情况来看,该程序执行的结果跟普通的ping几乎没有什么差别。