如何将数组从C++传递至Python?需修改包装器以一次性获取数组
如何从C++包装器返回整个数组到Python
看起来你现在的问题是原代码只能返回数组的第一个元素,没法把整个数组传递给Python对吧?我来帮你修改一下代码,让你能一次性获取整个数组。
首先说原代码的问题:你的Test::ret()里return *vec其实只是返回了数组第一个元素的值(也就是0),完全没法传递整个数组的内容。要解决这个问题,我们需要让C++把数组的首地址和长度暴露给Python,然后在Python端用ctypes来解析这块连续的内存。
修改后的C++代码
#include <iostream> using namespace std; class Test{ public: int* get_array(); int get_array_length(); }; // 这里用全局数组示例,你也可以把它改成Test类的成员变量 int vec[10] = {0,1,2,3,4,5,6,7,8,9}; int* Test::get_array(){ return vec; // 返回数组的首指针,这样Python能找到内存起始位置 } int Test::get_array_length(){ // 计算数组的元素个数,sizeof(vec)是总字节数,除以单个元素的字节数 return sizeof(vec)/sizeof(vec[0]); } // 外部C接口,供Python调用 extern "C" { Test* Test_new(){ return new Test();} int* Test_get_array(Test* test){ return test->get_array();} int Test_get_array_length(Test* test){ return test->get_array_length();} }
编译成共享库
先把这段代码编译成Python能加载的共享库:
g++ -shared -fPIC test.cpp -o libtest.so
修改后的Python代码
接下来用ctypes来处理返回的指针,转换成Python能直接用的列表:
from ctypes import cdll, POINTER, c_int lib = cdll.LoadLibrary('./libtest.so') # 告诉ctypes函数的返回类型和参数类型,避免类型解析错误 lib.Test_new.restype = c_int # 这里用c_int占位Test*,也可以用py_object lib.Test_get_array.restype = POINTER(c_int) lib.Test_get_array_length.restype = c_int class Test: def __init__(self): self.obj = lib.Test_new() def get_array(self): arr_ptr = lib.Test_get_array(self.obj) length = lib.Test_get_array_length(self.obj) # 把指针指向的连续内存转换成Python列表,两种方式都可以: # 方式1:遍历索引 # return [arr_ptr[i] for i in range(length)] # 方式2:直接切片(ctypes指针支持切片) return arr_ptr[:length] # 测试一下 if __name__ == "__main__": test_instance = Test() my_array = test_instance.get_array() print(my_array) # 会输出 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
额外注意事项
- 如果你的数组是Test类的成员变量(不是全局的),要确保Test对象在Python中存活期间,数组的内存不会被释放,避免出现悬垂指针。
- 如果数组是动态分配的(比如用
new int[10]),记得在C++里加一个释放内存的接口,比如void Test_free_array(Test* test),然后在Python调用完数组后手动释放,防止内存泄漏。
内容的提问来源于stack exchange,提问作者user6855072
相关产品推荐
相关产品推荐

