在SWIG中为包含union的结构创建一个typemap(Python)

时间:2014-08-15 00:17:28

标签: python c struct swig unions

我是使用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 };格式成功地创建了其他几个指针输出。

我已经阅读了大多数关于类型地图和Python类型地图的SWIG文档。我非常自信我理解它们是如何编写的以及它们如何工作的概念,但是这个结构应该如何进行类型映射的复杂性让我感到难过。

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

有人能为我提供一个如何做的例子吗?我无法在任何地方找到我需要的示例级别。

我真的很感激所提供的任何帮助。

- 编辑 -

我在Python中的用途是看起来像这样:

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

some_expr值是元组或字典或其他内容。这可能是不可能的,但我愿意接受如何使它成为某种格式的输出的建议,然后我可以在Python中使用它来提取定义的union值。

C函数的所有指针参数都用作输出,其中*类型告诉用户要查看哪个指针值。

1 个答案:

答案 0 :(得分: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文档),但这种方法应该相当简单。