在SWIG中为包含联合体的结构创建类型映射(Python)

0 投票
1 回答
922 浏览
提问于 2025-04-18 17:21

我刚开始使用SWIG,正在为以下结构体创建一个Python的类型映射,但遇到了一些困难:

typedef struct si2drExprT
{
    si2drExprTypeT type;
    union
    {
        si2drInt32T i;
        si2drFloat64T d;
        si2drStringT s;    /* most likely an identifier */
        si2drBooleanT b;
    } u;

    si2drValueTypeT valuetype; /* if the type is a fixed value */

    struct si2drExprT *left; /* the exprs form a classic binary tree rep of an arithmetic expression */
    struct si2drExprT *right;
} si2drExprT;

目前这个结构体在一个函数调用中被使用:

si2drVoidT    si2drIterNextComplexValue ( si2drValuesIdT iter,
  si2drValueTypeT *type,
  si2drInt32T     *intgr,
  si2drFloat64T   *float64,
  si2drStringT    *string,
  si2drBooleanT   *boolval,
  si2drExprT      **expr,
  si2drErrorT     *err )

我需要si2drExprT **expr作为输出,而不是指针。我已经成功地用%apply int *OUTPUT { si2drErrorT* err };的格式创建了几个其他指针的输出。

我读过大部分关于SWIG的文档,特别是关于类型映射和Python类型映射的部分。我对它们的写法和工作原理有一定的理解,但对于这个结构体应该如何进行类型映射,我还是感到困惑。

我不能切换到ctypes,因为最终我还需要为Perl做同样的事情,而SWIG似乎是转换成多种语言的最佳选择(这是我所知道的)。而且我无法控制C函数的定义,我的包装转换必须独立于C库。

有没有人能给我一个示例让我知道该怎么做?我找不到我需要的那种示例。

我非常感谢任何提供的帮助。

-- 编辑 --

我在Python中的预期使用方式大概是这样的:

(some_int, some_flt, some_str, some_bool, some_expr, error) = si2drIterNextComplexValue(some_iter)

其中some_expr的值是一个元组或字典之类的东西。虽然这可能不完全可行,但我希望能有一些建议,如何将其作为输出,以便我可以在Python中提取定义的联合值。

所有传递给C函数的指针参数都被视为输出,*类型告诉用户应该查看哪个指针值。

1 个回答

0

使用SWIG,你可以完全改变接口的方式。比如,你可以在你的.i文件中创建一个新的类,这个类用来存储指针,并返回这个类的一个实例:

// .i file: 

... what you have already to export si2dr* types ...

struct ExprWrapper {
    si2drValueTypeT type;
    si2drInt32T     intgr;
    si2drFloat64T   float64,
    si2drStringT    string;
    si2drBooleanT   boolval;
    si2drExprT      *expr;
    si2drErrorT     err;
};

%inline %{
ExprWrapper si2drIterNextComplexInt(si2drValuesIdT iter) {
    ExprWrapper wrapper;
    si2drIterNextComplexInt(iter, & wrapper.type, ..., & wrapper.expr, & wrapper.err);
    return wrapper;
)
%}

你可能需要告诉SWIG谁拥有ExprWrapper中的expr字段(是你自己还是Python -- 可以查看SWIG的文档),但这种方法应该比较简单明了。

撰写回答