SWIG:在Python中结构体中的自定义类型和赋值

1 投票
2 回答
932 浏览
提问于 2025-04-18 06:49

我的C++代码大概是这样的:

struct Data
{
    CustomType member;
};

我的swig .i文件里有%typemap(in)和%typemap(out),用来把Python字符串转换成CustomType(这个在参数和返回值上都能正常工作)

在我的Python代码中,我这样做:

d = Data()
d.member = "Hello"

但是在运行时,Python给我报了这个错误:

TypeError: in method 'Data_member_set', argument 2 of type 'CustomType *'

我尝试了以下方法,但都没有效果:

%typemap(memberin) CustomType
{
    $target = *$source;
}

我该怎么做才能让Python允许我给那个成员赋值呢?

2 个回答

0

你需要写一些像这样的代码:

%typemap(in) CustomType* (CustomType tmp, int res)
// or even: %typemap(in) CustomType* ($*1_type tmp, int res)
{
  if (PyString_Check($input))
  {
    tmp = (PyString_AsString($input));
    $1 = &tmp;
  }
  else
  {
    res = SWIG_ConvertPtr($input, (void **) &$1,$1_descriptor, 0 |  0 );
    if (!SWIG_IsOK(res)) {
      SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'.\n"
        "  Possible argument types are: 'string' and '" "$*1_type" "'\n");
    }
  }
}

这意味着以下几点:

  1. Python不允许你重写赋值运算符。相反,SWIG会为你C++代码中所有可能的赋值生成包装函数。在每一个可能出现“= ”的地方,它都会插入调用这个包装函数的代码。
  2. 通过上面的'typemap',你可以用a) CustomType类型和b) 内置的Python字符串来初始化一个CustomType对象。
  3. 'typemap'中的代码只是SWIG生成的包装函数代码的一部分。
  4. 你在包装函数中定义了一个CustomType的局部变量。第一行括号中的代码是局部变量,它们的作用范围是整个函数。

我建议你打开*_pywrap.cxx文件(这个文件是SWIG生成的),看看它实际上是根据你的'typemap'生成了什么。

想了解更多细节,可以查阅官方文档:http://www.swig.org/Doc1.3/SWIGDocumentation.html

0

如果一个 CustomType 可以通过字符串来创建,那么你应该可以这样做:

d.member = CustomType("Hello")

如果这样做失败了,那可能是因为你没有通过 .i 文件导出 CustomType,或者它没有一个可以接收字符串的构造函数。

撰写回答