使用Python的ctypes调用涉及自定义类型的函数

时间:2017-12-09 03:06:22

标签: python c++ c wrapper ctypes

我目前正在尝试使用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 ++函数的反向场景。

类似的问题很有帮助,但并非完全如此:

1 个答案:

答案 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封装器并不困难。