結構體傳參:http://www.jb51.net/article/52513.htmpython
準備工做:c++
C++文件(cpp):(注意在函數聲明上加上extern "C" 的修飾)數組
#include <stdio.h> extern "C" { __declspec(dllexport) int Double(int x); __declspec(dllexport) float floatAdd(float a,float b); __declspec(dllexport) void HelloWorld(char * str); __declspec(dllexport) void Ints(int * arr,int n); } int Double(int x){ return x*2; } float floatAdd(float a,float b) { return a+b; } void HelloWorld(char * str){ puts(str); } void Ints(int * arr,int n){ for(int i=0;i<n;i++){ printf("%d ",arr[i]); } puts(""); }
用g++(mingw64位)編譯爲dll:數據結構
g++ dlltest.cpp -shared -o dlltest.dll -Wl,--out-implib,dlltest.lib pause
在python腳本中加載dll :函數
from ctypes import * dll = cdll.LoadLibrary('DLL/dlltest.dll')
1.若是不加任何修飾,默認傳入參數爲int,傳出參數也爲intspa
2.對於int之外的類型(如float),須要聲明python函數的傳入參數類型,傳出參數類型.net
fun.argtypes=[c_float,c_float] #定義傳參類型 fun.restype=c_float #定義返回值類型 a=fun(c_float(1.4),c_float(1.2)) print(type(a)) print(a)
輸出:指針
<class 'float'> 2.5999999046325684
3.對於字符串char* ,在聲明傳入參數類型時,須要聲明爲字符指針,而後分配一塊char數組,最後把這個數組強制轉換爲字符指針rest
而且,在把python腳本中的數據結構導入c++中時,須要把str轉換爲bytes或者bytesarray類型,而且進行迭代器分解code
hello=dll.HelloWorld hello.argtypes=[POINTER(c_char)] #傳入參數爲字符指針 STR=(c_char * 100)(*bytes("相信你還在這裏",'utf-8')) #把一組100個的字符定義爲STR cast(STR, POINTER(c_char)) hello(STR)
輸出:
相信你還在這裏
4.對於其餘數據類型的數組,(例如int*),操做類似:
Ints=dll.Ints Ints.argtypes=[POINTER(c_int),c_int] INT=(c_int * 100)(*[1,2,3]) #把列表傳入變長參數args*中 cast(INT, POINTER(c_int)) Ints(INT,c_int(3))
輸出:
1 2 3
5.對於返回值爲數組的狀況,能夠直接使用索引去訪問,可是下標操做[]不是從迭代器中取對象,而是地址偏移:
def fillHoleCpp(im): dll = cdll.LoadLibrary("bfs.dll") bfs=dll.bfs bfs.argtypes = [POINTER(c_int),c_int] bfs.restype = POINTER(c_int) a = np.asarray(range(16), dtype=np.int32).reshape([4, 4]) if not a.flags['C_CONTIGUOUS']: a = np.ascontiguous(a, dtype=a.dtype) # 若是不是C連續的內存,必須強制轉換 IMG = cast(a.ctypes.data, POINTER(c_int)) # 轉換爲ctypes,這裏轉換後的能夠直接利用cty cast(IMG, POINTER(c_int)) length=a.size ans=bfs(IMG,c_int(length)) print(type(ans)) for i in range(0,length): print(ans[i],end=' ')