你如何包装一个需要预分配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**
并生成一个列表,我会使用新的,它还需要我指定分配的名称的长度。
更新:
我将这个问题简化为基本问题,以确保我一开始就做对了:
源代码:
//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()
我想使用的调用是期待某种我做得不对的预分配内存,因此参数要求每个字符的大小。