用于分配结构列表的C函数的Python Swig接口

rdlzhqv9  于 2023-01-27  发布在  Python
关注(0)|答案(1)|浏览(120)

我正在尝试将下面的C函数公开为python接口。

void myfunc(struct MyStruct** list, int* size) {
    int n = 10;
    *size = n;
    *list = (struct MyStruct*) malloc(n * sizeof(struct MyStruct));
    for (int i = 0; i < n; i++) {
        (*list)[i].x = i;
        (*list)[i].y = i * 0.1;
    }
}

不幸的是,swig文档并没有帮助我们缩小解决方案的范围,你能提供一些指针或代码参考,告诉我们如何编写一个相应的swig接口文件,使这个函数能从python中调用吗?
如果我能在python中以对象列表的形式访问它,那将是一个额外的奖励。

uxhixvfz

uxhixvfz1#

一种方法(省略错误检查):

    • SWIG接口文件-test. i**
%module test

%{ // code to include directly in the wrapper
#include <stdlib.h>
#include <stdio.h>

struct MyStruct {
    int x;
    double y;
};

void myfunc(struct MyStruct** list, int* size) {
    int n = 10;
    *size = n;
    *list = (struct MyStruct*) malloc(n * sizeof(struct MyStruct));
    for (int i = 0; i < n; i++) {
        (*list)[i].x = i;
        (*list)[i].y = i * 0.1;
    }
}
%}

// On input, do not require the list/size parameters.
// Instead, declare tmp variables and pass them by reference
// to capture the output arguments.
%typemap(in, numinputs=0) (struct MyStruct** list, int* size) (struct MyStruct* tmp, int size) %{
    $1 = &tmp;
    $2 = &size;
%}

// After the function call, append the returned pointer and size to the output result.
%typemap(argout) (struct MyStruct** list, int* size) %{
    PyObject* obj = SWIG_NewPointerObj(*$1, $descriptor(struct MyStruct*), 0);
    PyObject* s = PyLong_FromLong(*$2);
    $result = SWIG_Python_AppendOutput($result, obj);
    $result = SWIG_Python_AppendOutput($result, s);
%}

// Use the pre-defined SWIG typemaps to handle C pointers and arrays.
%include <carrays.i>
%include <cpointer.i>
%pointer_functions(struct MyStruct, pMyStruct);
%array_functions(struct MyStruct, MyStructArray);

// Make Python wrappers for the below struct and function.
struct MyStruct {
    int x;
    double y;
};

void myfunc(struct MyStruct** list, int* size);
    • Python测试文件-www.example.comexample.py
import test

# Helper function to put all the returned data in a list
# and manage the allocated pointer.
def myfunc():
    ptr, size = test.myfunc()
    try:
        arr = []
        objs = [test.MyStructArray_getitem(ptr, i) for i in range(size)]
        return [(obj.x, obj.y) for obj in objs]
    finally:
        test.delete_pMyStruct(ptr)

print(myfunc())

输出:

[(0, 0.0), (1, 0.1), (2, 0.2), (3, 0.30000000000000004), (4, 0.4), (5, 0.5), (6, 0.6000000000000001), (7, 0.7000000000000001), (8, 0.8), (9, 0.9)]

相关问题