如何实现C++ vector函数与Python的ctypes跨语言绑定?
解决ctypes调用C++ std::vector操作函数的问题
extern "C"仅支持C语言原生类型,std::vector是C特有的模板容器,C编译器无法识别其类型,且C模板函数的名字修饰规则与C不兼容,导致无法被ctypes正确识别和调用。因此不能直接把std::vector作为extern "C"函数的参数或返回值,以下是两种可行的解决方法:
方案1:用C兼容的数组+长度替代vector
这是最简单直接的方案,将vector操作转换为C风格数组操作,完全避开C++特有类型。
C++代码(vecadd.cpp)
#include <vector> #include <algorithm> // 导出C风格接口 extern "C" { void add_to_array(int* arr, int len, int n) { // 若已有基于vector的业务逻辑,可先将数组转为vector处理 std::vector<int> vec(arr, arr + len); std::for_each(vec.begin(), vec.end(), [n](int& num) { num += n; }); // 将结果写回原数组 std::copy(vec.begin(), vec.end(), arr); } }
编译为动态库
Linux/macOS:
g++ -shared -fPIC -o libvecadd.so vecadd.cpp
Windows:
g++ -shared -o vecadd.dll vecadd.cpp
Python调用代码
import ctypes # 加载动态库 lib = ctypes.CDLL('./libvecadd.so') # Windows环境替换为'./vecadd.dll' # 声明函数参数类型 lib.add_to_array.argtypes = (ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int) lib.add_to_array.restype = None # 测试数据 nums = [12, 10, 2, 14] n = 2 # 将Python列表转为C兼容数组 arr = (ctypes.c_int * len(nums))(*nums) # 调用函数 lib.add_to_array(arr, len(nums), n) # 转换回Python列表 result = list(arr) print(result) # 输出: [14, 12, 4, 16]
方案2:封装vector为不透明指针(void*)
若必须保留std::vector的使用,可将其包装为void*传递,导出一组C风格函数完成创建、操作、销毁的全流程。
C++代码(vecwrapper.cpp)
#include <vector> #include <algorithm> extern "C" { // 创建空的vector<int>,返回不透明指针 void* create_int_vector() { return new std::vector<int>(); } // 向vector添加元素 void vector_push_back(void* vec_ptr, int val) { auto* vec = static_cast<std::vector<int>*>(vec_ptr); vec->push_back(val); } // 给vector所有元素加指定数值 void vector_add_n(void* vec_ptr, int n) { auto* vec = static_cast<std::vector<int>*>(vec_ptr); std::for_each(vec->begin(), vec->end(), [n](int& num) { num += n; }); } // 获取vector长度 int vector_size(void* vec_ptr) { auto* vec = static_cast<std::vector<int>*>(vec_ptr); return vec->size(); } // 获取vector指定位置的元素 int vector_get(void* vec_ptr, int index) { auto* vec = static_cast<std::vector<int>*>(vec_ptr); return (*vec)[index]; } // 销毁vector,释放内存 void destroy_vector(void* vec_ptr) { delete static_cast<std::vector<int>*>(vec_ptr); } }
编译为动态库
使用与方案1相同的编译命令,生成libvecwrapper.so或vecwrapper.dll
Python调用代码
import ctypes lib = ctypes.CDLL('./libvecwrapper.so') # 声明各函数的参数与返回类型 lib.create_int_vector.argtypes = () lib.create_int_vector.restype = ctypes.c_void_p lib.vector_push_back.argtypes = (ctypes.c_void_p, ctypes.c_int) lib.vector_push_back.restype = None lib.vector_add_n.argtypes = (ctypes.c_void_p, ctypes.c_int) lib.vector_add_n.restype = None lib.vector_size.argtypes = (ctypes.c_void_p,) lib.vector_size.restype = ctypes.c_int lib.vector_get.argtypes = (ctypes.c_void_p, ctypes.c_int) lib.vector_get.restype = ctypes.c_int lib.destroy_vector.argtypes = (ctypes.c_void_p,) lib.destroy_vector.restype = None # 操作流程 vec_ptr = lib.create_int_vector() try: # 添加元素 for num in [12, 10, 2, 14]: lib.vector_push_back(vec_ptr, num) # 执行加操作 lib.vector_add_n(vec_ptr, 2) # 获取结果 size = lib.vector_size(vec_ptr) result = [lib.vector_get(vec_ptr, i) for i in range(size)] print(result) # 输出: [14, 12, 4, 16] finally: # 必须销毁vector,避免内存泄漏 lib.destroy_vector(vec_ptr)
内容的提问来源于stack exchange,提问作者IceCode
相关产品推荐
相关产品推荐

