我使用python的ctypes调用so库,然后其他普通的指针就可以调用,但是这种类似于python字典请问应该怎么调用,最好贴个代码
你得先将std::map转换为普通的指针,在传递给so库
#include <map>
#include <stdint.h>
extern "C" {
void* map2ptr(std::map<int32_t, int32_t>* map) {
return static_cast<void*>(map);
}
}
在py加载执行
import ctypes
from ctypes import *
lib = cdll.LoadLibrary("./libtest.so")
class IntMap(Structure):
_fields_ = [("key", c_int32),
("value", c_int32)]
lib.map2ptr.restype = c_void_p
lib.map2ptr.argtypes = [POINTER(c_void_p)]
py_dict = {1: 10, 2: 20, 3: 30}
cpp_map = [IntMap(k, v) for k, v in py_dict.items()]
map_ptr = lib.map2ptr(cpp_map)
这里并不是想黑 ctypes,只是在最初使用的方案中,利用 ctypes 加载 C/C++ 程序编译的动态库文件,之后调用函数,并返回值,整个过程似乎是没有问题,但应该只是看起来没有问题而已。单个测试程序运行正常,Python 中能够调用函数,得到想要的效果。但是将其应用到 Python 多线程程序中,就会出现错误。查看 core 文件,最终出错地点是 Python 类中调用 C/C++ 函数相关实例回收的函数,出现了段错误,导致程序宕掉。
当时段时间内没有得到问题所在原因,就改为使用写 Python 扩展的形式。在学习和使用扩展的过程中,也逐渐意识到问题可能是什么原因导致的。
Python 程序和 C/C++ 程序在运行时,对于所需要的空间,各自开辟、各自回收。因此,二者在空间利用上最好不要有交集。使用 Python 扩展的形式这一点就很明确:扩展会通过 PyArg_ParseTuple 函数将 Python 中传递过来的参数解析,用 C/C++ 中的变量或者缓冲区接收,相当于对原数据进行一次拷贝,而不是直接在原数据上操作。在向 Python 返回数据时,不是直接返回 C/C++ 程序的结果,而是根据 C/C++ 程序中的结果构建 Python 数据(或者说是对象)。这样既完成了两种程序之间的数据通信,两种程序又不会互相干扰。