2011-03-27 79 views
4

我最近已將用C++編寫的Boost Python wraping庫轉換爲C,並使用SWIG封裝來支持更多語言。 我從C++切換到C,因爲庫只包含一組函數,我也希望庫可以從C調用(而不必使用C++編譯器編譯整個程序)。 但是,有一件事不容易移植,一小部分功能需要將錯誤報告回來。 在C++/Boost中,用throw和異常轉換非常優雅地完成了Python。SWIG最優雅的方式包裝C庫以引發異常

什麼是最優雅的方式(在C語言和包裝語言方面)有一個函數子集報告錯誤?

回答

5

這就是我的做法。 %{...%}塊將其內容插入到包裝文件中。 %例外塊是SWIG的異常處理,並在每次函數調用後運行,以檢查是否有錯誤,並在PyErr_SetString(如果有)時拋出異常。然後,只需撥打「SET_ERR(」錯誤消息「);從你的C函數,如果你想拋出一個異常

%{ 
    /* Exception helpers */ 
    static int swig_c_error_num = 0; 
    static char swig_c_err_msg[256]; 

    const char *err_occurred() 
    { 
     if (swig_c_error_num) { 
      swig_c_error_num = 0; 
      return (const char*)swig_c_err_msg; 
     } 
     return NULL; 
    } 

    void set_err(const char *msg) 
    { 
     swig_c_error_num = 1; 
     strncpy(swig_c_err_msg, msg, 256); 
    } 
%} 

%exception { 
    const char *err; 
    $action 
    if (err = err_occurred()) { 
     PyErr_SetString(PyExc_RuntimeError, err); 
     return NULL; 
    } 
} 

另外,如果你的C庫使用一組標準的返回碼,你可以更換該機制在%異常塊中檢查函數的返回代碼。

%exception { 
    int rc; 
    rc = $action; 

    if (rc == ERR) { 
     PyErr_SetString(PyExc_RuntimeError, <err msg>); 
     return NULL; 
    } 
} 
0

請看Richard R. Hanson在C語言接口和實現中的第4章。