如何将结构列表/数组从python传递给C

时间:2015-04-28 21:05:52

标签: python c list pointers struct

我有一个C函数,必须可以从C和Python调用。

我无法弄清楚如何传递python的c-type结构列表, 每个都包含几个嵌套的结构,到c函数。

这些结构中的一个在python中看起来像这样:

class STATION_MM_NODE(ctypes.Structure):
    _fields_ = [
            ("signal", MM_STRUCT),
            ("noise", MM_STRUCT),
            ("signalWindowLen", ctypes.c_double),
            ("metadata", SAC_PZ)
    ]

在C:中就像这样:

typedef struct stationMMnode {
    struct mantleMagStruct *signal;
    struct mantleMagStruct *noise;
    double signalWindowLen;
    SAC_PZ metadata;
} stationMMnode_t;

采用一组stationMMnode结构的c函数可以调用为:

double magnitudeCompute_Mw_Mm_Event(stationMMnode_t **stationMMarray, int numStations);

例如,我可以在C中完全称之为:

int testfunc() {
    stationMMnode_t *node1 = malloc(sizeof(struct stationMMnode));
    node1->signalWindowLen = 500;
    stationMMnode_t *node2 = malloc(sizeof(struct stationMMnode));
    node2->signalWindowLen = 100;

    struct stationMMnode *nodes[2];
    nodes[0] = node1;
    nodes[1] = node2;

    magnitudeCompute_Mw_Mm_Event(nodes, 2); // Works!
}

在python中,我可以创建一个类似于c数组结构的节点列表:

stationMMnodes = []
...
node = get_stationMMnode() # Returns a STATION_MM_NODE
node.signal = mm_signal
node.noise  = mm_noise
node.metadata = sacPoleZero
stationMMnodes.append(node)
...
wrap_lib.magnitudeCompute_Mw_Mm_Event(stationMMnodes, numStations) # Does NOT work

我将argtypes定义为:

wrap_lib.magnitudeCompute_Mw_Mm_Event.argtypes =
    [ctypes.POINTER(STATION_MM_NODE), ctypes.c_int ]

我在上面使用的模型(将c-type指针传递给c-style结构到指向struct的指针的ac函数)似乎在我传入指向单个结构的指针时工作正常,但是,对于指向结构数组的指针,它似乎崩溃了。另外,我不确定python内存布局是什么结构列表与结构指针数组(正如C函数所期望的那样)。

非常感谢任何帮助!

更新:我发现以下链接非常有用: python ctypes array of structs

我解决了我的问题: 1.声明一个指向我的结构的指针数组:

nodeArrayType = ctypes.POINTER(STATION_MM_NODE) * 1024
nodeArray = nodeArrayType()
nstn = 0

2。编写一个C函数来连接成员结构成一个更大的结构(=一个节点)并返回一个指向该结构的指针 - 它存储在nodeArray []中。

nodeArray[nstn] = wrap_libmth.libmth.makeNode(node.signal, node.noise, node.metadata)
nstn += 1

3。修复接收指向struct array的指针的C函数的argtype:

wrap_libmth.libmth.magnitudeCompute_Mw_Mm_Event.argtypes = [ctypes.POINTER(ctypes.POINTER(STATION_MM_NODE)), ctypes.c_int]

所以...我有它的工作,但是像Python的大多数东西一样,我觉得我抓住了老虎的尾巴,因为我不完全理解为什么它有效和什么(更好) )备选方案是(例如,C hack makeNode()返回指向STATION_MM_NODE结构的指针不太令人满意 - 最好在python中完全生成这个结构。)

0 个答案:

没有答案