如何编写SWIG接口将C函数myfunc暴露为Python接口?
解决方案:用SWIG将C结构体数组转为Python对象列表
1. 整理C代码头文件
先把结构体和函数声明统一放到头文件mymodule.h中:
#ifndef MYMODULE_H #define MYMODULE_H typedef struct MyStruct { int x; double y; } MyStruct; void myfunc(MyStruct** list, int* size); #endif
2. 编写SWIG接口文件mymodule.i
核心是通过typemap处理C函数的输出参数,把动态分配的结构体数组转换成Python对象列表:
%module mymodule %{ #include "mymodule.h" #include <stdlib.h> %} // 让SWIG为MyStruct生成对应的Python绑定类 typedef struct MyStruct { int x; double y; } MyStruct; // 标记两个参数为输出参数,不需要Python传入值 %typemap(in, numinputs=0) MyStruct** list (MyStruct* temp) { $1 = &temp; } %typemap(in, numinputs=0) int* size (int temp) { $1 = &temp; } // 函数执行后,将C结构体数组转为Python对象列表 %typemap(argout) (MyStruct** list, int* size) { // 创建对应大小的Python列表 PyObject* py_list = PyList_New(*$2); for (int i = 0; i < *$2; i++) { // 生成MyStruct的Python实例,最后一个参数1表示让Python管理内存(自动回收) PyObject* py_obj = SWIG_NewPointerObj((*$1)[i], $descriptor(MyStruct), 1); PyList_SetItem(py_list, i, py_obj); } // 将列表作为函数返回值输出 $result = SWIG_Python_AppendOutput($result, py_list); } // 声明要暴露给Python的函数 void myfunc(MyStruct** list, int* size);
3. 编译与测试
编译步骤(Linux/macOS)
# 生成Python绑定代码 swig -python mymodule.i # 编译目标文件 gcc -fPIC -c mymodule.c mymodule_wrap.c -I/usr/include/python3.x # 编译为共享库 gcc -shared mymodule.o mymodule_wrap.o -o _mymodule.so
Python测试代码
import mymodule # 调用函数直接得到MyStruct对象列表 obj_list = mymodule.myfunc() for idx, obj in enumerate(obj_list): print(f"第{idx+1}个对象: x={obj.x}, y={obj.y}")
关键说明
- 输出参数处理:
typemap(in, numinputs=0)告诉SWIG这两个参数是输出用的,无需Python传入值,SWIG会自动创建临时变量接收结果。 - 内存管理:
SWIG_NewPointerObj最后一个参数设为1,让Python的垃圾回收机制负责释放C端malloc分配的内存,避免泄漏。如果需要手动管理内存,可将该参数设为0,并额外暴露一个内存释放函数。
内容的提问来源于stack exchange,提问作者Maverickgugu
相关产品推荐
相关产品推荐

