2016-12-13 10 views
1

の引数に私は、SWIGで遊ぶために始めました。私は "void *型" を期待し、私はCの関数にPythonの文字列を渡しているコードのこの部分を持っているSWIG:私はPythonでCライブラリを使用できるように、パスのPython文字列型がvoidポインタ

example.h:

char test(void *buf); 

はexample.c:

char test(void *buf) { 
    char *c = (char*)buf; 
    return *c; 
} 

Pythonの:

import example 
buf = "hello" 
example.test(buf) 

私はそれを実行すると、私は次のエラーを取得する:

TypeError: in method 'test', argument 1 of type 'void *' 

私は「のchar *」を「無効*」パラメータを変更した場合しかし、動作しているようです。私は "void *"がどんな種類のポインタにもマッチすると思ったので少し混乱しています。とにかく、私は周りを掘り出し、ctypesライブラリを見つけて、c_void_p(Python: converting strings for use with ctypes.c_void_p())にキャストしました。それは私にとってはうまくいきませんでした。私の周りの仕事として

は私のSWIGファイルでラッパーを作っ:

/* File: example.i */ 
%module example 
%include typemaps.i 

%{ 
#include "example.h" 
%} 

%include "example.h" 

%inline %{ 
    char test_wrapper(char *buf) { 
     void *voidBuf = (void*)buf; 
     return test(voidBuf); 
    } 
%} 

これは動作するようです。しかし、私はctypesのアプローチがうまくいかなかった理由について、誰かが説明を提供できるかどうか疑問に思っていました。私がctypesのアプローチで完全にマークから外れていた場合は、インラインラッパーを作成するよりも適切な方法がありますか?

ありがとうございました!

答えて

1

あなたのインラインラッパーアプローチは、直接、非常に使用できない機能を回避するには、音の一般的な方法です。一般的に、SWIGはターゲット言語の内部でCまたはC++の動作を模倣しようとします。この場合、あなたが観察したように、実際にはそうではありません。私はこの理由が二重であると思います:第一に、SWIGがサポートしている言語(Javaなど)の中でどうやってそれをやっていくのかは分かりません。第二に、Pythonで何かできることがあっても、この特定のケースでは一般的には役に立ちますが、void*は、どのように解釈/使用されるのかについての詳しいガイダンスなしでCプログラマにとってあいまいです。 CとPythonの間にはミスマッチがあります。文字列は参照カウントされ、Pythonでは不変なので、Pythonの動作がPythonプログラマーには全くわからないような状況に陥ることは非常に簡単です。キャストを実行するためにctypesを使って

はSWIGとctypesのは、物事と引数のタイピングをラップに根本的に非常に異なるアプローチを持って、実際に実行可能なソリューションではありません。

一般的なケースでは、他のオプションは、あなたのための変換/鋳造のためのいくつかのコードを生成するためにユーザ%include <cpointer.i>にある、(あなたは好奇心旺盛であれば私はかなりそれらの間detailed answer looking at interpoerabilityを書いた)例:

%pointer_cast(type1, type2, name) 

しかし、この場合には、あなたがchar*を使用しているので、その最初のノートのマニュアルの注意事項が適用されます。

Note: None of these macros can be used to safely work with strings (char * or char **).

Note: When working with simple pointers, typemaps can often be used to provide more seamless operation.

そして一般的に、私はでもう少しやっていることを第二のノートで作られたポイントを、好むと思います作業(例えば、オーバーロードを供給するために%inline)は、より直感的な動作を提供します。あなたの特定のケースでは、%rename(test) test_wrapper;を使用してPython内のオーバーロードにすることをお勧めします。(それがCの代わりにC++であれば、C++の中でオーバーロードすることができます)

関連する問題