0

char**結果を格納するための引数として事前に割り当てられていることを期待するC関数呼び出しをどのようにラップしますか?Pythonリストの結果を返そうとしています。

私は逆の例とこのctypesの例を見つけましたが、ctypesが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は単なるtypedefですchar

これがクラッシュするこれまでの私の試みです:

from libc.stdlib cimport malloc, free

def get_available_poses(self):
    cdef: 
        int i 
        bytes name 
        XnStatus stat
        XnUInt32 size = self.handle.GetNumberOfPoses()
        XnChar **buf = <XnChar**>malloc(size * sizeof(XnChar*))

    if not buf:
        raise MemoryError()

    try:
        # this crashes: Segmentation fault
        stat = self.handle.GetAvailablePoses(buf, size)

        # if I could get to here, I would want to 
        # build a list to return (not saying this is
            # even correct either)
        for i in range(size):
            name = <char*>(buf[i])
            ...

    finally:
        free(buf)

そのバージョンの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**割り当てられた名前の長さも指定する必要がある新しいものを使用します。

更新

私はこの問題を基本的なものに単純化して、最初からこれを正しく実行していることを確認しました。

src:

//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;
    }
}

cython:

#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()使用したい呼び出しは、私が正しく行っていないある種の事前に割り当てられたメモリを期待していると推測しています。したがって、パラメータは各文字のサイズを要求します。

4

1 に答える 1

0

私はついにこれを十分に遊んで理解しました。実際には、それぞれのスペースを事前に割り当てて、そのスペースが配置されるのにどれだけの大きさであるかを伝えること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']
于 2012-08-06T17:43:54.200 に答える