__str__()在打印用SWIG为Python包装的c++类时未调用
__str__() not called when printing C++ class wrapped for Python with SWIG
我正在尝试打印我使用SWIG为Python包装的c++类。我遵循文档和这个问题:如何在python中字符串化swig矩阵对象
扩展的__str__
函数在那里,但是当我从Python打印对象时没有调用它。让我举一个最小的例子:
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)
在构建(cmake ., make)之后,我得到以下内容:
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>
__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>
预期的输出将是在"print t"隐式地调用__str__()
。我错过了什么?
要让str(x)
为使用swig -python -builtin
生成的SWIG包装对象调用您自己的c++代码,您需要使用适当的插槽来注册您的函数。这是用SWIG中的%feature("python:slot", ...)
完成的,例如:
%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"; }
};
%}
与SWIG 2.0和Python 2.7让我运行:
import test
print str(test.foo())
print repr(test.foo())
结果是:
Hello world
<Swig Object of type 'foo *' at 0xb727ac40>
插槽允许快速调度标准对象函数调用-这是-builtin
为您带来的一大块。
您可以看到可用插槽及其类型的完整列表以及相应的SWIG 2.0文档。
基于Flexo的回答,这让我得到了我想要的功能(源文件和cmake不变)。
TestClass.i
%module TestClass
%{
#include <sstream>
#include "TestClass.h"
%}
%include "TestClass.h"
//http://stackoverflow.com/questions/2548779/how-to-stringfy-a-swig-matrix-object-in-python
%define __STR__(class_name)
%feature("python:slot", "tp_str", functype="reprfunc") class_name::py_to_string();
%extend class_name{
const char* py_to_string() {
std::ostringstream out;
out << *$self;
return out.str().c_str();
}
}
%enddef
__STR__(TestClass);
测试:
matthias@rp3deb:~/dvl/swig_str_minimal$ python -c "import TestClass; print TestClass.TestClass()"
TestClass: 0
相关文章:
- 如何在c++17中制作一个模板包装器/装饰器
- std::vector的包装器,使数组的结构看起来像结构的数组
- 如何在c++迭代器类型中包装std::chrono
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话
- 用pybind11包装C++抽象类时出错
- 为左值和右值的包装器实现C++范围
- C结构,其指针将被包装在unique_ptr中
- 如何包装第三方DLL在R中使用
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 将 N-arg 函数包装到另一个函数中
- 元组由 Swig 生成的 Python 包装器返回,用于C++向量
- 包装一个对象并假装它是一个 int
- 使用 Python Extension API 包装复杂C++类
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 包装C++类时不完整的类型 GLFWwindow
- 将函数包装器转换为 std::function
- C++函数包装器来捕获某些信号
- 创建包装升压适配器的自定义范围类
- 如何包装(撰写)增强 hana 地图并访问括号运算符(运算符 [])?
- 使用运算符*重载包装矩阵乘法