转载请注明出处:
参考网址:
importImagefrom ctypes importc_ubyte, cast, POINTER
buf= (c_ubyte * 400)()
pbuf=cast(buf, POINTER(c_ubyte))
pbuf2= cast(pbuf, POINTER(c_ubyte*400))
buf is an ubyte array, pbuf is a pointer to ubyte, pbuf2 is a pointer to ubyte[400]. img1 is created from buf directly, img2 is created from pubf2.contents.
一 传简单的指针:
具体步骤:
1. 新建mathBuf.cpp:
#include #include"subBuf.h"
extern "C"{int addBuf(char* data, int num, char*outData);
subBuf* subBuf_new(){ return newsubBuf(); }int subBuf_sub(subBuf* subfuf, char* data, int num, char* outData){ subfuf->cursubBuf(data, num, outData); }
}int addBuf(char* data, int num, char*outData)
{for (int i = 0; i < num; ++i)
{
outData[i]= data[i] + 3;
}returnnum;
}
2. 新建subBuf.h:
#include
classsubBuf{public:
subBuf(){}int cursubBuf(char* data, int num, char*outData)
{for (int i = 0; i < num; ++i)
{
outData[i]= data[i] - 5;
}returnnum;
}
};
3. 终端中输入如下命令,生成libmathBuf.so:
g++ -std=c++11 -shared -fPIC -o libmathBuf.so mathBuf.cpp
4. 新建test.py:
from ctypes import * #cdll, c_int
lib = cdll.LoadLibrary('libmathBuf.so')classcallsubBuf(object):def __init__(self):
self.obj=lib.subBuf_new()defcallcursubBuf(self, data, num, outData):
lib.subBuf_sub(self.obj, data, num, outData)
callAddBuf=lib.addBuf
num= 4numbytes=c_int(num)
data_in= (c_byte *num)()for i inrange(num):
data_in[i]=iprint("initial input data buf:")for i inrange(num):print(data_in[i])#pdata_in = cast(data_in, POINTER(c_ubyte))#pdata_in2 = cast(pdata_in, POINTER(c_ubyte*num))
data_out= (c_byte *num)()
ret=callAddBuf(data_in, numbytes, data_out)print("after call addBuf with C, output buf:")for i inrange(num):print(data_out[i])
f=callsubBuf()
f.callcursubBuf(data_in, numbytes, data_out)print("after call cursubBuf with C++ class, output buf:")for i inrange(num):print(data_out[i])
5. 运行test.py,输出如下:
说明:
1) test.py如果使用c_byte,则对应C中的unsigned char。
2) 程序使用了2个文件,subBuf.h和mathBuf.cpp。实际上可以使用一个文件,但是class要在extern "C"的上面,否则即便声明了class subBuf,也会提示invalid use of incomplete type ‘class subBuf’:
3) addSub函数的实现要在extern "C"的下面,否则会提示error: conflicting declaration of XXX with ‘C’ linkage:
4) ctypes中对应的c和python类型如下(具体参见ctypes的官方文档):
ctypes type
C type
Python type
c_bool
_Bool
bool (*)
c_char
char
1-character string
c_wchar
wchar_t
1-character unicode string
c_byte
char
int/long
c_ubyte
unsigned char
int/long
c_short
short
int/long
c_ushort
unsigned short
int/long
c_int
int
int/long
c_uint
unsigned int
int/long
c_long
long
int/long
c_ulong
unsigned long
int/long
c_longlong
__int64 or long long
int/long
c_ulonglong
unsigned __int64 or unsigned long long
int/long
c_float
float
float
c_double
double
float
c_longdouble
long double
float
c_char_p
char * (NUL terminated)
string or None
c_wchar_p
wchar_t * (NUL terminated)
unicode or None
c_void_p
void *
int/long or None
*. The constructor accepts any object with a truth value.
5) 除此之外:
提供了使用void*传递缓冲区的简单说明。
二 传结构体
1. 新建structPoint.cpp:
#include #include
structstructImg
{intwidth;intheight;intchannels;char*buf;
};extern "C"{voidshowStructureInfo(structImg p);
}voidshowStructureInfo(structImg p)
{
printf("%d %d %d\n", p.width, p.height, p.channels);for(int i=0;i< p.width*p.height*p.channels; ++i)
printf("%d: %d\n", i, p.buf[i]);
}
2. 终端中将该文件编译成.so库:
g++ -std=c++11 -shared -fPIC -o libstructPoint.so structPoint.cpp
3. 新建test.py:
from ctypes import *lib= cdll.LoadLibrary('libstructPoint.so')classstructImgTest(Structure):
_fields_=[('width', c_int),
('height', c_int),
('channels', c_int),
('buf', POINTER(c_ubyte))]defgetstructImg(width, height, channels):#cwidth = c_int(width)
#cheight = c_int(height)
#cchannels = c_int(channels)
num = width * height *channels
data_buf= (c_byte *num)()for i inrange(num):
data_buf[i]=i
pbuf=cast(data_buf, POINTER(c_ubyte))
st=structImgTest(width, height, channels, pbuf)returnst
width= 4height= 3channels= 2st=getstructImg(width, height, channels)
callTest=lib.showStructureInfo
callTest(st)printst.widthprintst.height#if declaration of test is test(structImg* p), then use the following line
pst = pointer(st) #not sure if "POINTER" points to ctypes type, while "pointer" points to a variable
printpst.contents.widthprint pst.contents.height
4. 终端中运行test.py,结果如下:
可见输出的结果正确。
=========================================================================
190130更新:
下面两个网址有使用ctypes的比较详细的说明,也可以参考一下。
190130更新结束
=========================================================================