【问题标题】:Most elegant way for SWIG wrapped C library to raise exceptionsSWIG 包装的 C 库引发异常的最优雅方式
【发布时间】:2011-03-27 09:11:07
【问题描述】:

我最近转换了一个库,我最初是用 C++ 编写的,带有 Boost Python 包装,到带有 SWIG 包装的 C,以支持更多语言。 我从 C++ 切换到 C,因为该库仅包含一组函数,并且我还希望可以从 C 调用该库(无需使用 C++ 编译器编译整个程序)。 然而,有一点不容易移植,一小部分功能需要能够报告错误。 在 C++/Boost Python 中,通过 throw 和异常翻译非常优雅地完成。

让函数子集报告错误的最优雅的方式是什么(在 C 和包装语言方面)?

【问题讨论】:

    标签: python c swig


    【解决方案1】:

    这就是我的做法。 %{...%} 块将其内容插入到包装文件中。 %exception 块是 SWIG 的异常处理,在每个函数调用之后运行以检查是否存在错误,如果存在则使用 PyErr_SetString 抛出异常。然后,如果您想抛出异常,只需从您的 C 函数中调用 "set_err("Error msg");。

    %{
        /* 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 块中检查函数的返回码来替换此机制。

    %exception {
        int rc;
        rc = $action;
    
        if (rc == ERR) {
            PyErr_SetString(PyExc_RuntimeError, <err msg>);
            return NULL;
        }
    }
    

    【讨论】:

      【解决方案2】:

      看看 Richard R. Hanson 在 C 接口和实现中的第 4 章。

      【讨论】:

        猜你喜欢
        • 2011-08-02
        • 2015-04-10
        • 1970-01-01
        • 2018-04-01
        • 2011-04-21
        • 1970-01-01
        • 2019-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多