使用 SWIG 打印为 Python 包装的 C++ 类时未调用 __str__() [英] __str__() not called when printing C++ class wrapped for Python with SWIG

查看:49
本文介绍了使用 SWIG 打印为 Python 包装的 C++ 类时未调用 __str__()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 SWIG 打印我为 Python 包装的 C++ 类.我遵循了文档和这个问题:How to stringfy a swigpython中的矩阵对象

扩展的 __str__ 函数在那里,但是当我从 Python 打印对象时它没有被调用.让我举一个最小的例子:

TestClass.h

#include 类测试类{私人的:int my_int;民众:测试类():my_int(0){}朋友 std::ostream&运算符<<(std::ostream& o, TestClass const& t){○<<测试类:"<<t.my_int;返回o;}};

TestClass.cpp

#include "TestClass.h"int main(){使用命名空间标准;测试类 t;cout<<<<结束;}

TestClass.i

%define __STR__() \const char* __str__() {std::cout <<*$self <

CMakeLists.txt

cmake_minimum_required (VERSION 2.6)项目(battery_lib_cpp)设置(CMAKE_VERBOSE_MAKEFILE 1)FIND_PACKAGE(需要 SWIG)包括(${SWIG_USE_FILE})设置(CMAKE_SWIG_FLAGS-墙")#寻找PythonlibsFIND_PACKAGE(PythonLibs)INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})SET_SOURCE_FILES_PROPERTIES(TestClass.i PROPERTIES CPLUSPLUS ON)SET_PROPERTY(SOURCE TestClass.i PROPERTY SWIG_FLAGS "-builtin")SWIG_ADD_MODULE(TestClass python TestClass.i TestClass.cpp)

构建 (cmake ., make) 后,我得到以下内容:

matthias@rp3deb:~/dvl/swig_str_minimal$ pythonPython 2.7.8(默认,2014 年 7 月 26 日,15:25:14)[GCC 4.9.1] 在 linux2 上输入帮助"、版权"、信用"或许可"以获取更多信息.>>>导入测试类>>>t = TestClass.TestClass()>>>打印 t<位于 0x7f1dffcb2b90 的TestClass *"类型的 Swig 对象>>>>打印 t.__str__()测试类:0测试类:0>>>打印 t.__str__<0x7f1dffcb2b90处的TestClass对象的内置方法__str__>

__unicode__()

的另一个测试<预><代码>>>>导入测试类>>>t = TestClass.TestClass()>>>打印 str(t)<位于 0x7f6584ae4b58 的TestClass *"类型的 Swig 对象>>>>打印 t<位于 0x7f6584ae4b58 的TestClass *"类型的 Swig 对象>>>>打印 t.__unicode__()unicode:测试类:0测试类:0>>>打印 t.__unicode__<0x7f6584ae4b58处的TestClass对象的内置方法__unicode__>

预期输出是在print t"处隐式调用 __str__() .我错过了什么?

解决方案

要让 str(x) 为使用 swig 生成的 SWIG 包装对象调用您自己的 C++ 代码 -python -builtin 你需要使用适当的槽来注册你的函数.这是通过 SWIG 中的 %feature("python:slot", ...) 完成的,例如:

%module 测试%include %feature("python:slot", "tp_str", functype="reprfunc") foo::as_string;%排队 %{结构 foo {std::string as_string() const { return "Hello world";}};%}

使用 SWIG 2.0 和 Python 2.7,我可以运行:

导入测试打印 str(test.foo())打印 repr(test.foo())

结果:

Hello world<0xb727ac40 处类型为foo *"的 Swig 对象>

插槽允许快速调度标准对象函数调用 - 这是 -builtin 为您带来的很大一部分.

您可以查看完整的可用插槽列表及其类型以及相应的 SWIG 2.0 文档.

I'm trying to print C++ classes that I wrapped for Python using SWIG. I have followed the documentation and this question: How to stringfy a swig matrix object in python

The extended __str__ function is there, but it isn't called when I print the object from Python. Let me give a minimal example:

TestClass.h

#include <iostream> 

class TestClass{
private:
    int my_int;
public:
    TestClass():
        my_int(0)
    {}

    friend std::ostream& operator<< (std::ostream& o, TestClass const& t){
        o<< "TestClass: " << t.my_int;
        return o;
    }
};

TestClass.cpp

#include "TestClass.h"

int main(){
    using namespace std;
    TestClass t;
    cout << t << endl;
}

TestClass.i

%define __STR__() \
const char* __str__() { 
  std::cout << *$self << std::endl;
  std::ostringstream out; 
  out << *$self; \
  return out.str().c_str(); 
}

const char* __unicode__() { 
  std::cout << "unicode: " << *$self << std::endl;
  std::ostringstream out; 
  out << *$self; \
  return out.str().c_str(); 
}
%enddef

%extend TestClass{
    __STR__()
};

CMakeLists.txt

cmake_minimum_required (VERSION 2.6)
project (battery_lib_cpp)
set(CMAKE_VERBOSE_MAKEFILE 1)

FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})
SET(CMAKE_SWIG_FLAGS "-Wall")

#look for Pythonlibs
FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

SET_SOURCE_FILES_PROPERTIES(TestClass.i PROPERTIES CPLUSPLUS ON)
SET_PROPERTY(SOURCE TestClass.i PROPERTY SWIG_FLAGS "-builtin")

SWIG_ADD_MODULE(TestClass python TestClass.i TestClass.cpp)

After building (cmake ., make), I then get the following:

matthias@rp3deb:~/dvl/swig_str_minimal$ python
Python 2.7.8 (default, Jul 26 2014, 15:25:14) 
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import TestClass
>>> t = TestClass.TestClass()
>>> print t
<Swig Object of type 'TestClass *' at 0x7f1dffcb2b90>
>>> print t.__str__()
TestClass: 0
TestClass: 0
>>> print t.__str__
<built-in method __str__ of TestClass object at 0x7f1dffcb2b90>

Another test for __unicode__()

>>> import TestClass
>>> t = TestClass.TestClass()
>>> print str(t)
<Swig Object of type 'TestClass *' at 0x7f6584ae4b58>
>>> print t
<Swig Object of type 'TestClass *' at 0x7f6584ae4b58>
>>> print t.__unicode__()
unicode: TestClass: 0
TestClass: 0
>>> print t.__unicode__
<built-in method __unicode__ of TestClass object at 0x7f6584ae4b58>

Expected output would be to have __str__() called at "print t" implicitly. What am I missing?

解决方案

To get str(x) to call your own C++ code for a SWIG wrapped object that was produced with swig -python -builtin you need to use the appropriate slot to register your function. That's done with %feature("python:slot", ...) in SWIG, e.g.:

%module test

%include <std_string.i>

%feature("python:slot", "tp_str", functype="reprfunc") foo::as_string;

%inline %{
struct foo {
  std::string as_string() const { return "Hello world"; }
};
%}

With SWIG 2.0 and Python 2.7 lets me run:

import test

print str(test.foo())
print repr(test.foo())

Which results in:

Hello world
<Swig Object of type 'foo *' at 0xb727ac40>

Slots allow standard object function calls to be dispatched quickly - it's a big chunk of what -builtin gains you.

You can see the complete list of available slots and their types and the corresponding SWIG 2.0 documentation of them.

这篇关于使用 SWIG 打印为 Python 包装的 C++ 类时未调用 __str__()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆