SWIG学習ノート
SWIGヘルプの表示
swig--helpは言語特有のオプションを見ることができます.例えば、swig-java-help
SWIGインタフェースファイル構文簡単な例 初期化ブロック( に相当する.コード挿入 SWIGプリプロセッサは、C/C++プリプロセッサの拡張バージョンです.#includeに加えて、他のC/C++構文はSWIGによって解析され、対応するパッケージコードが生成されます.このため、SWIGはヘッダファイルを直接解析するパッケージコードswig-java-module example exampleを生成する.h マクロを使用して、SWIGコマンドをC/C++ヘッダファイルに追加します.SWIG命令構文は標準的なC構文ではないため、コンパイル時の構文エラー を回避するためにマクロによって分離する必要がある. は生成されない.リンクchar*グローバル変数char*タイプのグローバル変数が現れると、SWIG使用malloc()またはnewは、新しい値にメモリを割り当てます.具体的には、このような変数が としては、 を実現することができる. を解析しない. を生成する.は、 . typemap記述フォーマット作成フォーマット
swig--helpは言語特有のオプションを見ることができます.例えば、swig-java-help
-addextern - extern
-c ++ - C ++
-co <file> - SWIG <file>
-copyctor -
-cpperraswarn - #error #warning( )
-cppext <ext> - C ++ <ext>
( cxx, cpp PHP )
-copyright -
-debug-classes -
-debug-module <n> - 1-4 ,<n> csv
-debug-symtabs -
-debug-symbols -
-debug-csymbols - C
-debug-lsymbols -
-debug-tags -
-debug-template -
-debug-top <n> - 1-4 ,<n> csv
-debug-typedef - typedef
-debug-typemap -
-debug-tmsearch -
-debug-tmused -
-directors - ,
-dirprot - ( )
-D <symbol> - <symbol>( )
-E - ,
-external-runtime [file] - SWIG
-fakeversion <v> - SWIG <v>
-fcompact -
-features <list> - , <list>
, -features director,autodoc = 1
, 1
-fastdispatch -
-Fmicrosoft - Microsoft /
-Fstandard - /
-fvirtual - virtual 。
-help -
-I- -
-I <dir> - <dir> SWIG
-ignoremissing -
-importall - #include
-includeall - #include
-l <ifile> - SWIG <ifile>
-macroerrors -
-makedefault - / ( )
-M -
-MD - `-M -MF <file>', `-E'
-MF -
-MM - , SWIG
-MMD - `-MD' , SWIG
-module <name> - <name>
-MP -
-MT <target> -
-nocontract -
-nocpperraswarn - #error #warning
-nodefault -
-nodefaultctor -
-nodefaultdtor -
-nodirprot - director
-noexcept -
-nofastdispatch - ( )
-nopreprocess -
-notemplatereduce - typedef
-O - :
-fastdispatch -fvirtual
-o <outfile> - C / C ++ <outfile>
-oh <headfile> - C ++ <headfile>
-outcurrentdir -
-outdir <dir> - <dir>
-pcreversion - PCRE
-small -
-swiglib - SWIG
-templatereduce - typedef
-v -
-version - SWIG
-Wall - , -Wextra
-Wallkw -
-Werror -
-Wextra - :202,309,403,512,321,322
-w <list> - / , -w401,+ 321 - Warnings.html
-xmlout <file> - , XML <file>
Java ( -java )
-nopgcpp -
-noproxy -
-oldvarnames -
-package <name> - Java <name>
SWIGインタフェースファイル構文
%module mymodule #
%{ #%{%} , wrapper
#include "myheader.h"
%}
// Now list ANSI C/C++ declarations
int foo; #swig
int bar(int x);
%init
指令)%init %{ # module , ,java , python
init_variables();
%}
%inline
指令%inline %{ # (xx_wrap.cxx ) swig
/* Create a new vector */
Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}
%}
は、%{
/* Create a new vector */
Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}
%}
Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}
%begin %{
... code in begin section ... xx_wrap.cxx , ,
%}
%runtime %{
... code in runtime section ... %header
%}
%header %{
... code in header section ... %{%}
%}
%wrapper %{
... code in wrapper section ... SWIG
%}
%init %{
... code in init section ... , java xx_wrap.cxx ,
python SWIG_INIT
%}
%module base_module
%{
#include "base.h"
%}
%include "base.h"//SWIG #include, SWIG #include %include
#define STATUS 50// C , (get/set)
#define VERSION "1.1"
#ifdef SWIG //swig
%module foo
#endif
%import
命令SWIGは%import命令を使用して別のファイルに命令を含むことを提供する.例えば、%import“foo.i”
%import
の目的は、パッケージコードを実際に生成することなく、別のSWIGインタフェースファイルまたはヘッダファイルから特定の情報を収集することである.このような情報には、通常、タイプ宣言が含まれます.(たとえば、typedef)およびインタフェースでクラス宣言のベースクラスとして使用可能なC++クラス.SWIGが関連モジュールの集合として拡張機能を生成するために使用される場合、%importを使用することも重要です.これは詳細なトピックで、後でモジュールの章で説明します.この-importallコマンドは、SWIGに#includeを%importとして使用するように伝えます.システムヘッダファイルからタイプ定義を抽出する場合包装器を生成しないで、これは役に立つかもしれません.%immutable
命令変数を変更不可とマークすると、生成されたインタフェースファイルに読み取り専用メソッドgetが生成されるだけで、setメソッド// File : interface.i
int a; // Can read/write
%immutable;
int b, c, d; // Read only variables
%mutable;
double x, y; // read/write
char * foo;
//SWIG :
/ * C * /
void foo_set(char * value){
if(foo)free(foo);
foo =(char *)malloc(strlen(value)+1);
strcpy(foo,value);
}
/ * C ++ 。 -c++ * /
void foo_set(char * value){
if(foo)delete [] foo;
foo = new char [strlen(value)+1];
strcpy(foo,value);
}
ある場合は、%immutableコマンドを使用して変数を読み取り専用に設定することを考慮します.または、必要に応じて値を完全に設定するために短い補助関数を作成できます.たとえば、%inline %{
void set_foo(char * value){
strncpy(foo,value,50);
}
%}
注意:このような補助関数を作成する場合は、ターゲットスクリプト言語から関数と呼ばざるを得ません(変数のように動作しません).たとえば、Pythonでは、>>> set_foo(“Hello World”)
char*変数の一般的なエラーは、char * VERSION =“1.0”;
を宣言する変数にリンクされています.この場合、変数は読み取り可能になりますが、値を変更しようとすると、セグメントエラーや保護エラーが発生します.これはmallocを使用すると()またはnew変数に割り当てられている文字列の文字列値の場合、SWIGはfreeまたはdeleteを使用して古い値を解放しようとします.この問題を解決するには、変数を読取り専用としてマークしたり、タイプマッピングを記述したり、特殊なset関数を記述したりすることができます.別の方法は、変数を数グループとして宣言することです.char VERSION [64] =“1.0”;
宣言タイプがconst char*の変数の場合、SWIGは設定に使用する変数を生成します.と入力します.でも、デフォルトの動作では、以前の内容は解放されません.(メモリが漏洩する可能性があります).実際には、このような変数をパッケージすると、example.i:20という警告メッセージが表示されます.タイプ図の警告です.const char*変数を設定するとメモリが漏洩する可能性があります.この動作の原因は、const char*変数が文字列の文字列を指すために一般的に使用されるためです.たとえば、const char * foo =“Hello World \ n”;
は、このようなポインタでfreeを呼び出します.()は非常に悪いアイデアです.一方、ポインタを他の値に変更するのは正当です.このタイプの変数を設定すると、SWIGは新しい文字列(mallocまたはnewを使用)を割り当て、ポインタを新しい値に変更します.ただし、この値を繰り返し変更すると、古い値が解放されないためメモリが漏洩します.%constant
、%callback/%nocallback
コールバック関数ポインタ/ * * /
int binary_op(int a,int b,int(* op)(int,int));
/ * * /
%constant int add(int,int);
%constant int sub(int,int);
%constant int mul(int,int);
この場合、add,sub,mulは、ターゲットスクリプト言語における関数ポインタ定数となる.これにより、>>> binary_op(3,4,add)
7
>>> binary_op(3,4,mul)
12
>>>
を使用できます.残念ながら、コールバック関数を定数として宣言することで、関数としてアクセスできなくなります.関数をコールバック関数と関数として使用する場合は、次のように%callbackコマンドと%nocallbackコマンドを使用します./ * * /
int binary_op(int a,int b,int(* op)(int,int));
/ * * /
%callback( “%s_cb”);
int add(int,int);
int sub(int,int);
int mul(int,int);
%nocallback;
%callbackのパラメータはprintfスタイルのフォーマット文字列です.コールバック定数の命名規則を指定します(%sは関数名で置き換えられます).コールバックモードは、%nocallbackを使用して明示的に無効になるまで有効です.この操作を実行すると、インタフェースの現在の動作は、コールバックポインタ>>> binary_op(3,4,add_cb)
7
>>> binary_op(3,4,mul_cb)
12
>>> add(3,4)
7
>>> mul(3,4)
12
/* Some callback functions */
%callback("%(uppercase)s");
int add(int, int);
int sub(int, int);
int mul(int, int);
%nocallback;
にすべて大文字に変換されます.%extend
を使用してc言語struct構造体を拡張し、方法を構造体にバインドする.これにより、C++のようなクラスの効果/* file : vector.h */
...
typedef struct Vector {
double x, y, z;
} Vector
// file : vector.i
%module mymodule
%{
#include "vector.h"
%}
%include "vector.h"
// Just grab original C header file
%extend Vector {
// Attach these functions to struct Vector
Vector(double x, double y, double z) {
Vector *v;
v = (Vector *) malloc(sizeof(Vector));
v->x = x;
v->y = y;
v->z = z;
return v;
}
~Vector() {
free($self);
}
double magnitude() {
return sqrt($self->x*$self->x+$self->y*$self->y+$self->z*$self->z);
}
void print() {
printf("Vector [%g, %g, %g]
", $self->x, $self->y, $self->z);
}
};
%ignore
指定された名前を無視することにより、SWIGは指定された名前と生成コード%ignore foo(double); //Ignore all foo(double)
%ignore Spam::foo; //Ignore foo in class Spam
%ignore Spam::foo(double);//Ignore foo(double) in class Spam
%ignore *::foo(double);//Ignore foo(double) in all classes
%rename
すべてのクラスのメンバー関数名前を変更%rename(foo_i) *::foo(int);
指定したクラスのメンバー関数名前を変更%rename(foo_i) Spam::foo(int);
%rename(foo_d) Spam::foo(double);//
グローバル関数名前を変更%rename(foo_i) ::foo(int);
すべての関数(クラスメンバーと非クラスメンバー)%rename(foo_i) foo;
%template
実体化テンプレート%template(intList) vector<int>;
typedef int Integer;
...
void foo(vector<Integer> *x);
// traits, but don't
%template() traits<double, double>;
バッチ実体化%define TEMPLATE_WRAP(prefix, T...) // ..., ,
//std::pair 。 。
%template(prefix ## Foo) Foo<T >;
%template(prefix ## Bar) Bar<T >;
...
%enddef
TEMPLATE_WRAP(int, int)
TEMPLATE_WRAP(double, double)
TEMPLATE_WRAP(String, char *)
TEMPLATE_WRAP(PairStringInt, std::pair<string, int>)
...
強制テンプレートインスタンス生成デフォルトコンストラクタtemplate<class T1, class T2> struct pair {
T1 first;
T2 second;
pair() : first(T1()), second(T2()) { }
pair(const T1 &x, const T2 &y) : first(x), second(y) { }
template<class U1, class U2> pair(const pair<U1, U2> &x)
: first(x.first), second(x.second) { }
};
%extend pair {
%template(pair) pair<T1, T2>; //
};
// Instantiate a few versions
%template(pairii) pair<int, int>;
%template(pairdd) pair<double, double>;
// Create a default constructor only
%extend pair<int, int> {
%template(paird) pair<int, int>; // Default constructor
};
// Create default and conversion constructors
%extend pair<double, double> {
%template(paird) pair<double, dobule>;// Default constructor
%template(pairc) pair<int, int>;// Conversion constructor
}
%feature ref unref
参照カウントクラスのパッケージコードclass RCObj {
// implement the ref counting mechanism
int add_ref();
int del_ref();
int ref_count();
public:
virtual ~RCObj() = 0;
int ref() const {
return add_ref();
}
int unref() const {
if (ref_count() == 0 || del_ref() == 0 ) {
delete this;
return 0;
}
return ref_count();
}
};
class A : RCObj {
public:
A();
int foo();
};
class B {
A *_a;
public:
B(A *a) : _a(a) {
a->ref();
}
~B() {
a->unref();
}
};
%module example
...
%feature("ref") RCObj "$this->ref();"
%feature("unref") RCObj "$this->unref();"
%include "rcobj.h"
%include "A.h"
...
%newobject
%newobject
機能を使用して、オブジェクトの所有権を返すターゲット言語を取るべきであることを示すことを目的としている.これに関連付けられたrefプロパティのタイプとともに使用される場合、refフィーチャーのコードもC++パッケージに送信されます.上記以外に、%newobject AFactory;
A *AFactory() {
return new A();
}
%newobjectがスタックオブジェクトを返す方法を示す工場方法を検討してください.このようにして返されるC/C++スタックオブジェクトのライフサイクルは、ターゲット言語によって完全に管理される%newobject derived::bar;
%inline %{
class derived : public base {
public:
derived * bar(){
return new derived();
}
};
%}
%typemap(method [, modifiers]) typelist code ;
typelist : typepattern [, typepattern, typepattern, ... ] ;
typepattern : type [ (parms) ] int/* */ (int temp/* wrapper */)
| type name [ (parms) ] int len/* */ (int temp/* wrapper */)
| ( typelist ) [ (parms) ] (char *str, int len)/* */ (int temp/* wrapper */)
code : { ... } // {}
| " ... " // {}
| %{ ... %}// {}
typemap役割ドメインnamespace Foo {
class string;
%typemap(in) string { /* Foo::string */
...
}
}
typemap_example.i %module TypemapExample // java
//argxx wrapper
// , 。
// , , C/C++ ( %rename )。 ,
%typemap(typecheck , precedence=SWIG_TYPECHECK_INTEGER) int {
$1 = Custom_Check_Int($input) ? 1 : 0;// int
}
//
/* Required for C++ method overloading */
/*%typecheck(SWIG_TYPECHECK_STRING_ARRAY) (int argc, char *argv[]) {
$1 = PyList_Check($input) ? 1 : 0;
}*/
// ( C/C++ )
%typemap(arginit) int flags {
//arginit, wrapper
$1 = NULL;
}
%typemap(default) int flags {
//default, wrapper
$1 = DEFAULT_FLAGS;
}
%typemap(in) int flags {
//in, java c/c++ int
$1 = JavaObj_to_int($input);
}
%typemap(check) int flags {
//check,
if ($1 <= 0) {
SWIG_exception(SWIG_ValueError, "Expected positive value.");
}
}
%typemap(out) int foo {
//out,C/C++ ——
//\$\1,C/C++
$result = To_Java_Int($1);
}
%typemap(argout) int flags {
//argout,
$result += $1
}
%typemap(freearg) int flags {
//freearg
free($1);
}
%typemap(newfree) int {
//newfree, C/C++ 。 (%newobject)
delete $1;
}
%typemap(varin) int {
//varin, 。 python
$1 = PythonInt_To_C($input);
}
%typemap(varout) int {
//varout, 。 python
$1 = C_To_PythonInt($result);
}
int ALL_TIMES;
%typemap(ret) stringheap_t %{
//ret, C/C++
free($1);
%}
typedef char * string_t;
typedef char * stringheap_t;
string_t MakeString1();
stringheap_t MakeString2();
//numinputs 0 1
//0 wrapper , ,$input
//1 wrapper , ,$input
/*
%typemap(in, numinputs=0) int flags (int temp) {
$1 = &temp;
}*/
%newobject foo;
int foo(int x, int y, int flags);
/*%typemap(memberin) int x[20] {
//memberin,
memmove($1, $input, 4*sizeof(int));
}*/
%typemap(memberin) int x[ANY] {
//memberin, set C/C++
memmove($1, $input, $1_dim0*sizeof(int));
}
struct A {
int x[4];
};
%fragment("AsMyClassFragment", "header") {
//%fragment("AsMyClassFragment", "header")
MyClass *AsMyClassA(PyObject *obj) {
MyClass *value = 0;
return value;
}
}
%typemap(in, fragment="AsMyClassFragment") MyClass * {
//in, MyClass * , wrapper header fragment
$result = AsMyClassA($input);
}
%typemap(varin, fragment="AsMyClassFragment") MyClass * {
//varin
$result = AsMyClassA($input);
}
void foo(MyClass *a, MyClass *b);
%fragment("" , "header") {
%#include <limits.h>
}
%fragment("AsMyClass", "header", fragment="" ) {//fragment fragment
MyClass *AsMyClass(PyObject *obj) {
MyClass *value = 0;
... some marshalling code ...
if (ival < CHAR_MIN /*defined in */ ) {
...
} else {
...
}
...
return value;
}
}
//%fragment("bigfragment", "header", fragment="frag1", fragment="frag2", fragment="frag3") "";// fragment
//typemap fragment
//%typemap(in, fragment="frag1, frag2, frag3") {...}
//
//%typemap(in, fragment="bigfragment") {...}
// fragment
//%fragment("bigfragment");
// C/C++
//jstring jarg1 -> char *str, int len
%typemap(in) (char *str, int len) {
$1 = PyString_AsString($input);
/* char *str */
$2 = PyString_Size($input);
/* int len
*/
}
int foo(char *str, int len);
%typemap(in) const int* bar{
$symname
$argnum
$1_name
$1_type
$*1_type
$&1_type
$1_ltype
$*1_ltype
$&1_ltype
$1_basetype
$1_descriptor
$*1_descriptor
$&1_descriptor
$1_mangle
$*1_mangle
$&1_mangle
$descriptor(std :: vector <int> *)
}
int barf( const int *bar);
%typemap(in) (int argc, char *argv[]) {
int i;
if (!PyList_Check($input)) {
PyErr_SetString(PyExc_ValueError, "Expecting a list");
SWIG_fail;
}
$1 = PyList_Size($input);
$2 = (char **) malloc(($1+1)*sizeof(char *));
for (i = 0; i < $1; i++) {
PyObject *s = PyList_GetItem($input, i);
if (!PyString_Check(s)) {
free($2);
PyErr_SetString(PyExc_ValueError, "List items must be strings");
SWIG_fail;
}
$2[i] = PyString_AsString(s);
}
$2[i] = 0;
}
%typemap(freearg) (int argc, char *argv[]) {
if ($2) free($2);
}
%fragment("incode"{float}, "header") {
float in_method_float(PyObject *obj) {
}
}
%fragment("incode"{long}, "header") {
float in_method_long(PyObject *obj) {
}
}
// %my_typemaps macro definition
%define %my_typemaps(Type)
%typemap(in, fragment="incode"{Type}) Type {
value = in_method_##Type(obj);
}
%enddef
%my_typemaps(float);
%my_typemaps(long);
int foo(int argc, char *argv[]);
int agoda(long argc, char *argv[]);