私は次のようなCインターフェースを持っています(簡略化):
extern bool Operation(void ** ppData);
extern float GetFieldValue(void* pData);
extern void Cleanup(p);
これは次のように使用されます。
void * p = NULL;
float theAnswer = 0.0f;
if (Operation(&p))
{
theAnswer = GetFieldValue(p);
Cleanup(p);
}
Operation() がバッファ p を割り当て、GetFieldValue が p をクエリし、Cleanup が p を解放することに注意してください。私は C インターフェイスを制御することはできません。そのコードは他の場所で広く使用されています。
SWIGを介して Python からこのコードを呼び出したいのですが、ポインターをポインターに渡し、その値を取得する方法の良い例を見つけることができませんでした。
これを行う正しい方法は typemap を使用することだと思うので、C 側で p を自動的に逆参照するインターフェイスを定義しました。
%typemap(in) void** {
$1 = (void**)&($input);
}
ただし、次の Python コードを動作させることができませんでした。
import test
p = None
theAnswer = 0.0f
if test.Operation(p):
theAnswer = test.GetFieldValue(p)
test.Cleanup(p)
test.Operation() を呼び出した後、p は常に初期値の None を保持していました。
SWIG でこれを行う正しい方法を理解するための助けをいただければ幸いです。それ以外の場合は、C コードの周りに C++ ラッパーを記述して、Python がポインターを処理する必要がないようにする可能性があります。そして、そのラッパーを SWIG でラップします。誰か私を止めて!
編集:
Jorenkoのおかげで、次の SWIG インターフェイスを使用できるようになりました。
% module Test
%typemap (in,numinputs=0) void** (void *temp)
{
$1 = &temp;
}
%typemap (argout) void**
{
PyObject *obj = PyCObject_FromVoidPtr(*$1, Cleanup);
$result = PyTuple_Pack(2, $result, obj);
}
%{
extern bool Operation(void ** ppData);
extern float GetFieldValue(void *p);
extern void Cleanup(void *p);
%}
%inline
%{
float gfv(void *p){ return GetFieldValue(p);}
%}
%typemap (in) void*
{
if (PyCObject_Check($input))
{
$1 = PyCObject_AsVoidPtr($input);
}
}
この SWIG インターフェイスを使用する Python コードは次のとおりです。
import test
success, p = test.Operation()
if success:
f = test.GetFieldValue(p) # This doesn't work
f = test.gvp(p) # This works!
test.Cleanup(p)
奇妙なことに、python コードでは、test.GetFieldValue(p) は意味不明な結果を返しますが、test.gfv(p) は正しい値を返します。void* の typemap にデバッグ コードを挿入しましたが、両方とも p の値は同じです! それについて何かアイデアはありますか?
更新: ctypes を使用することにしました。はるかに簡単です。