通过Ctypes从C到Python – 将函数指针的结构包装到静态函数

我有一个像这样的C库中的结构。 DataFn中的函数指针指向静态函数。

。H

struct Data { int i; int *array; }; typedef struct { bool (* const fn1) (struct Data*, const char *source); .... } DataFn; extern DataFn const DATAFUNC 

使用objdump,该表仅包含DATAFUNC和gcc中的一些其他内容。

这在C中很好,其中调用fn1就像DATAFUNC.fn1(…,…),但是这样的东西怎么会被包裹起来所以fn1可以用python w / ctypes调用?

示例python

 libc = ctypes.cdll.LoadLibrary("./data.so") print(libc.DATAFUNC) 

导致

这是类似的,但没有工厂function。

[Python]:ctypes – Python的外部函数库包含解决此问题所需的一切。

我相信缺少的主要部分是ctypes类型的in_dll方法( 访问从dll部分导出的值 )。

除此之外,为了使用C数据,您需要让Python知道数据格式。 这适用于:

  • struct 。 通过ctypes.Structure定义Python对应物
  • 函数指针(适用于您的情况)。 使用ctypes.CFUNCTYPE定义它们

我准备了一个简化的例子,说明了上述内容。 请注意,我没有做任何error handling(检查NULL你应该 )),以保持简单。

ch

 struct Data { int i; }; typedef struct { int (* const fn1) (struct Data*, const char*); } DataFn; extern DataFn const DATAFUNC; 

cc

 #include  #include "ch" static int func1(struct Data *pData, const char *source) { printf("From C - Data.i: [%d], source: [%s]\n", pData->i, source); return -255; } DataFn const DATAFUNC = {&func1}; 

code.py

 import sys from ctypes import c_int, c_char_p, Structure, CDLL, CFUNCTYPE, POINTER, byref class Data(Structure): _fields_ = [ ("i", c_int), ] fn1_type = CFUNCTYPE(c_int, POINTER(Data), c_char_p) class DataFn(Structure): _fields_ = [ ("fn1", fn1_type), ] def main(): data = Data(127) dll = CDLL("./c.so") data_func = DataFn.in_dll(dll, "DATAFUNC") ret = data_func.fn1(byref(data), "abcd".encode()) print("DATAFUNC.fn1 returned {:d}".format(ret)) if __name__ == "__main__": print("Python {:s} on {:s}\n".format(sys.version, sys.platform)) main() 

输出

 [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> ls cc ch code.py [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> gcc -shared -fPIC -o c.so cc [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> ls cc ch code.py c.so [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> objdump -t c.so | grep DATAFUNC 0000000000200e10 g O .data.rel.ro 0000000000000008 DATAFUNC [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049962265]> python3 code.py Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] on linux From C - Data.i: [127], source: [abcd] DATAFUNC.fn1 returned -255