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