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

Posted

技术标签:

【中文标题】使用 Python 的 ctypes 调用涉及自定义类型的函数【英文标题】:Using Python's ctypes to call functions involving custom types 【发布时间】:2017-12-09 03:06:21 【问题描述】:

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


有帮助但不完全的类似问题:

How to use C++ classes with ctypes? Obtaining address of custom data-type in C from Python using ctypes

【问题讨论】:

【参考方案1】:

请注意,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 包装器并不难。

【讨论】:

以上是关于使用 Python 的 ctypes 调用涉及自定义类型的函数的主要内容,如果未能解决你的问题,请参考以下文章

Python 外部函数调用库ctypes简介

使用ctypes在Python中调用C++动态库

Python调用DLL动态链接库——ctypes使用

使用 CType 时检测从 Windows DLL 调用 Python 脚本

使用ctype在python中调用c

为啥 2019 年我们仍然不能使用 ctypes 从 Python 调用 C++?