SWIG 學習筆記

查看SWIG幫助

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 <file> - 生成<file>中的依賴項並繼續生成包裝器
     -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接口文件語法

  1. 簡單例子
    %module mymodule #指定生成的目標語言文件名
    %{                              #%{%}包含的部分,將會插入到wrapper中
    #include "myheader.h"
    %}
    // Now list ANSI C/C++ declarations
    int foo;                      #swig預處理器根據這裏的函數聲明生成相應的包裝方法
    int bar(int x);
    
  2. 初始化塊(%init指令)
    %init %{ #在module加載的時候調用,測試了一下,java沒有用,但是python有效果
    init_variables();
    %}
    
  3. %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));
    }
    
  4. 代碼插入
    %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方法內最後一行
    
    %}
    
  5. SWIG預處理器是C/C++預處理器的增強版本。除了#include之外,其它的C/C++語法都會被SWIG解析並生成相應的包裝代碼。
    基於這個原因,SWIG直接解析頭文件來生成包裝代碼 swig -java -module example example.h
    %module base_module
    %{
    #include "base.h"
    %}
    %include "base.h"//SWIG默認不解析#include,所以當需要讓SWIG預處理解析#include需要通過%include指令來達到
    #define STATUS 50//這些C語言語法會被解析,生成相應的包裝(get/set)方法
    #define VERSION "1.1"
    
  6. 使用宏在C/C++頭文件中添加SWIG指令。因爲SWIG指令語法不是標準的C語法所以需要通過宏來隔離,避免編譯時語法錯誤
    #ifdef SWIG //swig解析時會定義這個宏
    %module foo
    #endif
    
  7. %import指令
    SWIG使用%import 指令提供另一個文件包含指令。例如:
    %import“foo.i”
    %import的目的是從另一個SWIG接口文件或頭文件中收集某些信息,而不實際生成任何包裝器代碼。
    此類信息通常包括類型聲明(例如,typedef)以及可能用作接口中類聲明的基類的C ++類。當SWIG用於生成擴展作爲相關模塊的集合時,
    使用%import也很重要。這是一個高級主題,稍後將在使用模塊章節中進行介紹。
    該-importall指令告訴SWIG將#include作爲%import。如果要從系統頭文件中提取類型定義而不生成任何包裝器,這可能很有用。
  8. %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
    
  9. 鏈接char* 全局變量
    當出現char *類型的全局變量時,SWIG使用malloc()或 new爲新值分配內存。具體來說,如果你有這樣的變量
    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)並將指針更改爲指向新值。但是,重複修改該值將導致內存泄漏,因爲舊值未釋放。
  10. %constant%callback/%nocallback 回調函數指針
    / *帶回調函數* /
    int binary_op(int a,int b,int* op)(intint));
    
    / *一些回調函數* /
    %constant int add(intint;
    %constant int sub(intint;
    %constant int mul(intint;
    
    在這種情況下,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)(intint));
    
    / *一些回調函數* /
    %callback( “%s_cb”);
    int add(intint;
    int sub(intint;
    int mul(intint;
    %nocallback;
    
    %callback 的參數是一個printf樣式的格式字符串,它指定回調常量的命名約定(%s被函數名替換)。回調模式保持有效,直到使用%nocallback顯式禁用它。執行此操作時,界面現在的工作方式如下:
    >>> binary_op(3,4,add_cb)
    7
    >>> binary_op(3,4,mul_cb)
    12
    >>> add(3,47
    >>> mul(3,412
    
    全部轉爲大寫來作爲回調指針
    /* Some callback functions */
    %callback("%(uppercase)s");
    int add(int, int);
    int sub(int, int);
    int mul(int, int);
    %nocallback;
    
  11. 使用%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]\n", $self->x, $self->y, $self->z);
    }
    };
    
  12. %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
    
  13. %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;
    
  14. %template 實例化模板
    %template(intList) vector<int>;
    typedef int Integer;
    ...
    void foo(vector<Integer> *x);
    
    // 實例化 traits<double, double>, but don't 生成包裝代碼
    %template() traits<double, double>;
    
    批量實例化
    %define TEMPLATE_WRAP(prefix, T...) //這裏使用...,是因爲不這樣做的話, 
    //std::pair<string, int>中的逗號就不能使用了。在宏這裏變量是以逗號作爲每個單位的分隔符。
    %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
    }
    
  15. %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"
    ...
    
  16. 使用%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();
    }
    };
    %}
    
  17. typemap
    編寫格式編寫格式
    %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("<limits.h>", "header") {
    %#include <limits.h>
    }
    
    %fragment("AsMyClass", "header", fragment="<limits.h>") {//fragment依賴fragment
    MyClass *AsMyClass(PyObject *obj) {
    MyClass *value = 0;
    
    ... some marshalling code ...
    
    if (ival < CHAR_MIN /*defined in <limits.h>*/) {
    ...
    } 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[]);
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章