python调用c 接口_python调用C接口
5、結(jié)構(gòu)體定義
我們用 fields = [(‘name1’,type1),(‘name2’,type2)]來表示結(jié)構(gòu)體的成員
字節(jié)對(duì)齊 C結(jié)構(gòu)體中經(jīng)常會(huì)出現(xiàn)按照指定的字節(jié)進(jìn)行對(duì)齊結(jié)構(gòu)體,用pack來指定對(duì)齊的字節(jié)數(shù),數(shù)組的定義直接用 *num 表示個(gè)數(shù)
C
#pragma pack(1)
structMyStruct
{inta;doubleb;char c[32];
};#pragma pack()
python
classMyStruct(Structure):
_fields_=[
('a',c_int),
('b',c_double),
('c',c_char*32),
]
_pack_= 1
位域
C
structMyStruct1
{int a : 16;int b : 16;
};
python
classMyStruct1(Structure):
_fields_=[
('a',c_int,16),
('b', c_int, 16),
]
結(jié)構(gòu)體的嵌套
c
structMyStruct2
{inta;
MyStruct S[4];
};
classMyStruct2(Structure):
_fields_=[
('a',c_int),
('struct',MyStruct*4)
]
傳遞結(jié)構(gòu)體,與之前傳遞參數(shù)一樣,指針類型用byref或者pointer
c
DLL1_API int fnDLL5(MyStruct &s)
{
printf("mystruct:\na:%d\nb:%f\nc:%s\n", s.a, s.b, s.c);return 1;
}
python
mystruct =MyStruct()
mystruct.a= 1mystruct.b= 1.0mystruct.c= 'helloworld'.encode('gbk')
dll.fnDLL5(byref(mystruct))
dll.fnDLL5(pointer(mystruct))
返回結(jié)構(gòu)體,與之前相同,需要指定返回的類型
c
DLL1_API MyStruct fnDLL6()
{
MyStruct*tem = newMyStruct;
tem->a = 10;
tem->b = 20;
sprintf(tem->c, "hello");return *tem;
}
python
dll.fnDLL6.restype =MyStruct
res=dll.fnDLL6()print(res)print('mystruct:', res.a, res.b, res.c)del res
高階數(shù)組的定義
int my_array[10][10];
#先定義一個(gè)數(shù)組類型
type_int_array_10 = c_int * 10
#定義數(shù)組的數(shù)組(即二維數(shù)組)
type_int_array_10_10 = type_int_array_10 * 10
#創(chuàng)建二維數(shù)組對(duì)象
my_array =type_int_array_10_10()#使用二維數(shù)組
my_array[1][2] = 3
字節(jié)流與結(jié)構(gòu)體的相互轉(zhuǎn)換
#pack
print(string_at(addressof(mystruct),sizeof(mystruct)))#unpack
buf =bytes(sizeof(MyStruct))assertlen(buf)
buf=create_string_buffer(sizeof(MyStruct))
res=cast(pointer(buf),POINTER(MyStruct)).contentsprint(res,type(res))print('mystruct:',res.a,res.b,res.c)
defPack(ctype_instance):returnstring_at(addressof(ctype_instance),sizeof(ctype_instance))defUnPack(ctype,buf):assert sizeof(ctype) ==len(buf)
cstring=create_string_buffer(buf)return cast(pointer(cstring),POINTER(ctype)).contents
回調(diào)函數(shù)
先用CFUNCTYPE 定義回調(diào)函數(shù)類型,參數(shù)的第一個(gè)參數(shù)為返回值類型
后面的參數(shù)為回調(diào)函數(shù)傳遞的參數(shù)類型,然后定義python中的函數(shù),
C
typedef int (*callbakc) (int a, intb);
DLL1_APIvoid fnDLL7(int a, intb, callbakc func)
{int n =func(a, b);
printf("c++ callback %d\n", n);
}
python
CMPFUNC =CFUNCTYPE(c_int,c_int,c_int)
cmp_func=CMPFUNC(callFunc)
dll.fnDLL7(1,2,cmp_func)
這里有個(gè)地方特別注意,如果回調(diào)函數(shù)中有void* ,char等類型,在python中定義回調(diào)函數(shù)的時(shí)候如果定義為 c_void_p ,c_char_p,實(shí)際返回的數(shù)據(jù)為int,bytes
這時(shí)候其實(shí)python內(nèi)部已經(jīng)把參數(shù)的值拿出來了,而我們需要的是char地址的內(nèi)容,常用的比如傳遞某一串字節(jié)流,我們需要傳遞出字節(jié)流的長度和首地址的指針,如果直接使用參數(shù),c_void_p拿到的是一個(gè)int類型,而c_char_p拿到的是截止到最后一個(gè)'\0'的字節(jié),最終我們?cè)趐ython中用string_at 來拿到實(shí)際的字節(jié)流
c回調(diào)
typedef void (*callbakc) (void * buf, int &buf_size);
python中的定義
string = string_at(buf,size.value)
defcallback(buf,size):
string=string_at(buf,size.value)
CALLBACKFUNC=CFUNCTYPE(None,c_void_p,c_int)
call= CALLBACKFUNC(callback)
總結(jié)
以上是生活随笔為你收集整理的python调用c 接口_python调用C接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python excel操作xlrd_p
- 下一篇: python导入不在同一路径的函数_py