我目前正在尝试使用Python 3.6的ctypes模块从用C ++编写的库中调用函数。
假设我使用ctypes创建了一个名为myLibrary的共享库对象:
# Python code
myLibrary = ctypes.CDLL(mylib.dylib)
我试图通过使用C ++类进行调用的库,ctypes不可能使用myLibrary.class()->method()
形式进行Python调用(参见here)。
因此,我首先编写了一些中间C ++代码,它以非类形式“包装”C ++类方法。例如,假设Math
是其中一个类,Add()
是其中一个方法。我的中间包装器看起来像这样:
// C++ intermediate code
int Add(int num1, int num2){ // no reference to a class
return Math()->Add(num1, num2); // reference to a class
}
然后我计划将这个C ++编译成一个共享库(一个dylib文件),我可以使用ctypes在Python上进行调用。例如:
# Python code
def add(num1, num2):
myLibrary.add(num1, num2)
这就是计划。
不幸的是,库中的许多方法都有异乎寻常的参数和值类型。有些只是使用typedef
关键字创建的变体类型名称,但其他名称是异域结构。此外,原始C ++代码中有一些枚举。
我的问题是:在使用ctypes时如何处理自定义参数和值类型(以及枚举)?
查看ctypes documentation,我知道你必须为你试图调用的方法指定restypes和argtypes,但是当原始的C ++函数涉及奇特的类型和结构时,如何做到这一点?
我认为ctypes文档可能会在第15.17.1.6节中阐明这一点。 (“使用您自己的自定义数据类型调用函数”),但它只是讨论了您希望将自己的对象类型传递给C ++函数的反向场景。
类似的问题很有帮助,但并非完全如此:
答案 0 :(得分:2)
请注意,ctypes旨在调用 C 代码,而不是 C ++ 。
由于您已经在编写包装器,因此您只需要更改一件事 - 指定这些包装器函数具有 C 链接:
// C++ intermediate code
extern "C" int Add(int num1, int num2) { // no reference to a class
return Math()->Add(num1, num2); // reference to a class
}
至于结构等,你应该为那些定义一个合适的 C 语言界面。为此提出ctypes
封装器并不困难。