包装一个C函数调用接受char**[in/out],以在cython中返回python列表

2024-05-17 08:10:38 发布

您现在位置:Python中文网/ 问答频道 /正文

{如何将pre}result}作为一个赋值函数来处理?我试图返回python列表结果。

我已经找到了另一种方法的例子,还有this ctypes example,但我并不完全确定cytypes是cython中合适的方法。在

作为参考,我正在练习包装openni库:
http://openni.org/Documentation/Reference/classxn_1_1_pose_detection_capability.html

我包装的原始C签名是(实际上是一个C++方法,它只围绕C函数内部):

/**
 * @brief Gets the names of all poses supported by this capability.

 * @param [out]     pstrPoses   Pre-allocated memory for the names of the supported poses.
 * @param [in,out]  nPoses      In input - size of the preallocated memory, in output
 *                              - the number of pose names.
 */

XnStatus GetAvailablePoses(XnChar** pstrPoses, XnUInt32& nPoses) const

XnChar只是char的typedef)

以下是我目前为止的尝试,但失败了:

^{pr2}$

这个版本的C函数在技术上是不推荐使用的,但是在我看来,新版本的C函数看起来更可怕:

/**
 * Gets the names of all poses supported by this capability.

 * @param [out]     pstrPoses       Pre-allocated memory for the names of the supported poses.
 * @param [in]      nNameLength     Memory size for each pose name.
 * @param [in,out]  nPoses          In input - size of the preallocated memory, in output
 *                                  - the number of pose names.
 */

 XnStatus GetAllAvailablePoses(XnChar** pstrPoses, XnUInt32 nNameLength, 
                                XnUInt32& nPoses) const;

理想情况下,如果我能弄清楚如何传入一个正确的char**并生成一个列表,那么我将使用新的列表,它还要求我指定分配的名称的长度。在

更新

我将这个问题简化为一些基本问题,以确保我在第一时间正确地完成了这项工作:

源代码:

//chars.h

void setChars(char** str_array, int size);

//chars.cc

#include "chars.h"

void setChars(char** str_array, int size) {
    for (int i = 0; i < size; i++) {
        char *s = "FOO";
        str_array[i] = s;
    }
}

赛顿:

#chars.pxd

cdef extern from "chars.h":
    void setChars(char**, int)

#chars.pyx

from libc.stdlib cimport malloc, free

def py_setChars():
    cdef: 
        bytes s
        int i
        int size = 6
        char** buf = <char**>malloc(size * sizeof(char*))

    if not buf:
        raise MemoryError()

    out = []

    try:
        setChars(buf, size)

        for i in range(size):
            s = buf[i]
            out.append(s)

    finally:
        free(buf)

    return out

正如预期的那样:

In [1]: import chars
In [2]: chars.py_setChars()
Out[2]: ['FOO', 'FOO', 'FOO', 'FOO', 'FOO', 'FOO']

我猜我想使用的GetAllAvailablePoses()调用需要某种类型的预分配内存,但我做得不对,因此参数要求每个字符的大小。在


Tags: ofthe函数inforsizefooparam
1条回答
网友
1楼 · 发布于 2024-05-17 08:10:38

我终于想明白了。GetAllAvailablePoses确实希望您预先分配每个char*的空间,并告诉它该空间有多大以便填充:

# foo.pxd

XnStatus GetAllAvailablePoses(XnChar **, XnUInt32, XnUInt32&)

# foo.pyx

def get_available_poses(self):
    cdef: 
        int i 
        bytes name 
        XnStatus stat
        XnUInt32 nameLength = 256
        XnUInt32 size = self.handle.GetNumberOfPoses()

    cdef XnChar **buf = <XnChar**>malloc(size * sizeof(XnChar*))

    if not buf:
        raise MemoryError()

    for i in range(size):
        buf[i] = <XnChar*>malloc(nameLength)

    out = [None]*size

    try:
        stat = self.handle.GetAllAvailablePoses(buf, nameLength, size)

        for i in range(size):
            name = <char*>buf[i]
            out[i] = name

    finally:
        free(buf)

    return out

# Out: ['Psi', 'CrossHandsPose', 'Wave', 'Click', 'RaiseHand', 'MovingHand']

相关问题 更多 >