从 Python 调用 C++ 64 位共享库

Posted

技术标签:

【中文标题】从 Python 调用 C++ 64 位共享库【英文标题】:Calling C++ 64bit shared library from Python 【发布时间】:2015-02-21 09:38:58 【问题描述】:

我想使用来自 python 2.7.8 的给定 C++ 64 位共享库(linux 下的 .so 文件)中的函数。

C++共享库的The header有这个功能:

EXPORT_CODE double CONVENTION PropsSI(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char *Ref);

我需要一个不需要修改共享库的 C++ 代码的解决方案(一个完整的 Python 包装器已经与自定义库一起存在)。

这是基于以下答案的有效解决方案:

>>> import ctypes
>>> lib = ctypes.cdll.LoadLibrary("/PathTo/libCoolProp.so")
>>> PropsSI = lib.PropsSI
>>> PropsSI.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_double, ctypes.c_char_p, ctypes.c_double, ctypes.c_char_p)
>>> PropsSI.restype = ctypes.c_double
>>> result = PropsSI(b"H", b"T", 300., b"P", 101325., ctypes.create_string_buffer("Water", 8))
>>> result
112654.89965373254

还有另一种写法:

>>> from ctypes import *
>>> CoolProp = cdll.LoadLibrary('/PathTo/libCoolProp.so')
>>> PropsSI = CoolProp.PropsSI
>>> PropsSI.restype = c_double
>>> print PropsSI(c_char_p("H"), c_char_p("T"),c_double(300.),c_char_p("P"),c_double(101325.),c_char_p("Water"))
112654.899654

【问题讨论】:

ctypes 应该可以正常工作。函数的argtypesrestype你设置了吗?为什么不分享您如何在 python 中设置函数以及尝试调用它时发生了什么。 “寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。 @Dunes @Antii 我更新了问题。你是对的,这可能是argtypes 的更多问题。 我认为这是与 32 位和 64 位不同的约定的问题,但似乎不是。因此,该问题与***.com/q/145270 重复 【参考方案1】:

ctypes 会为你做很多类型转换。

例如,给定在string.h中定义的函数strchr

const char * strchr ( const char * str, int character );

您可以提供函数的参数类型和返回类型,而不必自己进行任何类型强制 - ctypes 模块会为您处理。唯一的例外是当您需要将 char * 作为输出(可变)参数传递时。使用ctypes.create_string_buffer 创建此参数,并使用value 属性访问内容。

import ctypes

libc = ctypes.cdll.LoadLibrary("msvcrt")
# or on linux
# import ctypes.util
# libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))

strchr = libc.strchr

strchr.argtypes = (ctypes.c_char_p, ctypes.c_char)
strchr.restype = ctypes.c_char_p

result = strchr(b"abcde", b"c")
assert result == b"cde"

注意ctypes 如何自动将字符串参数转换为适当的类型,并能够将返回值转换回 python 字符串。

【讨论】:

您正在使用库的夜间构建,其documentation 表示该函数采用std::string 参数而不是char * - 这可以解释段错误。但是,该库存在 python 绑定。为什么不直接使用它们——sourceforge.net/projects/coolprop/files/CoolProp/5.0.7/Python 抱歉,没有看到这条评论。导出函数时,在转换为std::string 之前需要一个char *。完整的 python 绑定直接使用带有std::string 的 C++ 函数,但我需要制作一些快速测试包装器来测试共享库。以这种方式访问​​仅用于测试目的。 (从其他包装器访问库时,我遇到了奇怪的崩溃,我需要其他参考才能查看问题出在哪个级别。最后,问题出在与其他包装器一起使用的软件的 deb 包装中)

以上是关于从 Python 调用 C++ 64 位共享库的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 调用共享库

从 amd64 可执行文件调用 aarch64 共享库,可能使用二进制翻译/QEMU

从堆栈跟踪中查找共享库中的源代码行

将第三方共享库与 Python ctypes 集成

从 python 中的共享库返回的数组 - 这是内存泄漏吗?

Python 和 C++ 共享相同的内存资源