2013-08-07 112 views
1

我有兩個結構(從第三方LIB其實)在我痛飲.i文件遵循這種形式:痛飲void *的參數

typedef struct MY_STRUCT { 
    void*  pParameter; 
    unsigned long pLen; 
} MY_STRUCT; 
%extend MY_STRUCT 
{ 
    MY_STRUCT() 
    { 
     MY_STRUCT *m= new MY_STRUCT(); 
     m->pParameter = NULL; 
     m->pLen = 0; 
     return m; 
    } 
} 

typedef struct ANOTHER_STRUCT { 
    char * another; 
    unsigned long len; 
} ANOTHER_STRUCT; 
%extend ANOTHER_STRUCT 
{ 
    ANOTHER_STRUCT() 
    { 
     ANOTHER_STRUCT *p= new ANOTHER_STRUCT(); 
     p->another = NULL; 
     p->len = 0; 
     return p; 
    } 
    unsigned long __len__() 
    { 
     return sizeof(ANOTHER_STRUCT); 
    } 
} 

的pParameter在MY_STRUCT是一個void *,因爲它可以是一個char *或指向結構的指針(如ANOTHER_STRUCT)。只使用%typemap(in) void* = char*;來處理char *映射很簡單,但是任何使用結構的嘗試都會失敗。以下是我想在Python中看到的內容:

s = MY_STRUCT() 
another = ANOTHER_STRUCT() 
s.pParameter = another # this should pass the struct pointer 
s.pParameter = "some string" # or a char pointer if this is provided 

這可能嗎?如果沒有,我是否需要聲明一些幫助函數來分配指針值?

+0

鑑於你使用'new'關鍵字,我有點困惑,你爲什麼需要爲構造函數使用'%extend',但除此之外。 – Flexo

回答

1

你可以用SWIG來做到這一點。您將最終編寫fairly large if來選擇如何處理Python輸入,具體取決於您想要處理的類型。下面是你需要兩個typemaps一個完整的示例:

%module test 

%typemap(in) void* pParameter (int res=0, void *other_struct=NULL) %{ 
    int len; 
    res = SWIG_ConvertPtr($input, &other_struct, $descriptor(struct ANOTHER_STRUCT*), 0); 
    if (SWIG_IsOK(res)) { 
    fprintf(stderr, "struct\n"); 
    $1 = reinterpret_cast< ANOTHER_STRUCT * >(argp1); 
    len = sizeof(ANOTHER_STRUCT); 
    } 
    else if (PyString_Check($input)) { 
    $1 = PyString_AsString($input); 
    len = strlen((const char*)$1); 
    fprintf(stderr, "string\n"); 
    } 
    //else if (...) { 
    //} 
    else { 
    SWIG_exception_fail(SWIG_TypeError, "some more details, see special typemap variables docs for ideas"); 
    } 
%} 

%typemap(memberin) void* pParameter %{ 
    $1 = $input; //fobar $self 
    $self->pLen = len; 
%} 

%inline %{ 
typedef struct MY_STRUCT { 
    void*  pParameter; 
    unsigned long pLen; 
} MY_STRUCT; 

typedef struct ANOTHER_STRUCT { 
} ANOTHER_STRUCT; 
%} 

%extend MY_STRUCT 
{ 
    MY_STRUCT() 
    { 
     MY_STRUCT *m= new MY_STRUCT; 
     m->pParameter = NULL; 
     m->pLen = 0; 
     return m; 
    } 
} 

這裏in類型映射需要的PyObject並計算出如何處理它。它還將長度保存到局部變量中。

memberin typemap使用它來適當地設置void*和長度。

您可能需要考慮使pLen不可變(請參閱:%immutable),以便人們不能隨意更改該指針。您還需要仔細考慮像這樣的類型映射的內存所有權語義,以避免泄漏或雙重釋放。

+0

謝謝柔印,我會盡快檢查。 –