你必须完全匹配论点。设定
.argtypes
和
.restype
你使用的每一个函数
ctypes
可以正确地将参数封送到C并再次封送回来。如果你不设定
.重新键入
ctypes
假设返回值为
c_int
(通常是有符号的32位整数)而不是(可能是64位)指针。
下面是一个有效的例子。我并没有充实每个函数,因为一个函数应该足够了。在32位和64位Python上进行了测试。
测验cpp(使用MS编译器cl/LD/EHsc/W4 test.cpp构建):
#include <stdio.h>
// Needed to export functions on Windows
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
class CMatrix
{
public:
CMatrix(int d1) : s1(d1) { m = new float[d1]; }
~CMatrix() { delete [] m; }
const float* Get(int& s) { s = s1; return m; }
void Set(int x, float f) { m[x] = f; }
int s1;
float *m;
};
extern "C" {
API CMatrix* CMatrix_new(int i) {return new CMatrix(i); }
API const float* CMatrix_Get(CMatrix* cm, int& x) { return cm->Get(x); }
API void CMatrix_Set(CMatrix* cm, int x, float f) { cm->Set(x, f); }
API void CMatrix_delete(CMatrix* cm) { delete cm; }
}
测验py
import ctypes as ct
# For type checking the returned pointer.
class _CMatrix(ct.c_void_p) : pass
PCMatrix = ct.POINTER(_CMatrix)
class CMatrix:
_dll = ct.CDLL('./test')
_dll.CMatrix_new.argtypes = ct.c_int,
_dll.CMatrix_new.restype = PCMatrix
_dll.CMatrix_Get.argtypes = PCMatrix, ct.POINTER(ct.c_int)
_dll.CMatrix_Get.restype = ct.POINTER(ct.c_float)
_dll.CMatrix_Set.argtypes = PCMatrix, ct.c_int, ct.c_float
_dll.CMatrix_Set.restype = None
_dll.CMatrix_delete.argtypes = PCMatrix,
_dll.CMatrix_delete.restype = None
def __init__(self, i):
self.obj = self._dll.CMatrix_new(i)
def Set(self, x, f):
self._dll.CMatrix_Set(self.obj, x, f)
def Get(self):
size = ct.c_int()
m = self._dll.CMatrix_Get(self.obj, ct.byref(size))
return m[:size.value]
def __del__(self):
self._dll.CMatrix_delete(self.obj)
cm = CMatrix(2)
cm.Set(0, 1.5)
cm.Set(1, 2.5)
print(cm.Get())
输出:
[1.5, 2.5]