Boost/Python: returning internal reference
I have a simple C++ class that I've wrapped using Boost/Python,
v1.29.0 (on Win 2K), and that has a simple accessor returning a const
ref to an internal string. In the python interpreter, the accessor
raises an exception (see below),whereas another access that returns a
copy of the string works. Could someone explain my mistake?
--bruce
------ Bar.cpp --------
#include <string>
class Bar
{
public:
Bar( const std::string& s ) : m_s( s ) {}
std::string get_s_copy() const { return m_s; }
const std::string& get_s_ref() const { return m_s; }
std::string m_s;
};
#include
import Foo bar = Foo.Bar("hello") bar.m_s 'hello' bar.get_s_copy() 'hello' bar.get_s_ref() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: bad argument type for built-in operation
"Bruce Lowery
I have a simple C++ class that I've wrapped using Boost/Python, v1.29.0 (on Win 2K), and that has a simple accessor returning a const ref to an internal string. In the python interpreter, the accessor raises an exception (see below),whereas another access that returns a copy of the string works. Could someone explain my mistake?
C++ strings are exposed to Python as Python strings by default. return_internal_reference<> builds a Python object around a pointer to the C++ result object (which must have a class_<> wrapper somewhere)q, and applies some lifetime management to keep the "self" object alive as long as the Python result is alive. If you want it to work, you could write class_std::string("string")... to create a std::string wrapper. I'm not sure you'd be getting the result you want, though: it wouldn't be a Python string. You could expose enough of std::string's operators to make it look like a Python string, of course. -- David Abrahams dave@boost-consulting.com * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution
Could you briefly map out how to expose the std::string methods so
that the wrapper looks like a python string?
In my test program, I defined a simple 'class_' as you suggested:
class_std::string("string")
;
However, I don't understand how to properly expose the std::string
methods since the python string method arguments are not mirrors of
those in std::string class.
For instance, at this point, I could only naively try to define
a 'find(sub,first,last)' method in the class_std::string wrapper,
in terms of a std:string method, say 'std::string( const char *s,
size_type i, size_type n)':
class_std::string("string")
.def( "find", &std::string::find )
;
I don't expect this to compile, much less execute with expected
results.
I realize this may be a "newbie" (which I am) question. I have been
scanning the extensive documentation, but it's not yet coming
together in my head.
--bruce
--- In Boost-Users@yahoogroups.com, David Abrahams
"Bruce Lowery
" writes: I have a simple C++ class that I've wrapped using Boost/Python, v1.29.0 (on Win 2K), and that has a simple accessor returning a const ref to an internal string. In the python interpreter, the accessor raises an exception (see below),whereas another access that returns a copy of the string works. Could someone explain my mistake?
C++ strings are exposed to Python as Python strings by default.
return_internal_reference<> builds a Python object around a pointer to the C++ result object (which must have a class_<> wrapper somewhere) q, and applies some lifetime management to keep the "self" object alive as long as the Python result is alive. If you want it to work, you could write class_std::string("string")... to create a std::string wrapper. I'm not sure you'd be getting the result you want, though: it wouldn't be a Python string. You could expose enough of std::string's operators to make it look like a Python string, of course.
-- David Abrahams dave@b... * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution
"Bruce Lowery
Could you briefly map out how to expose the std::string methods so that the wrapper looks like a python string?
In my test program, I defined a simple 'class_' as you suggested:
class_std::string("string") ;
However, I don't understand how to properly expose the std::string methods since the python string method arguments are not mirrors of those in std::string class.
For instance, at this point, I could only naively try to define a 'find(sub,first,last)' method in the class_std::string wrapper, in terms of a std:string method, say 'std::string( const char *s, size_type i, size_type n)':
class_std::string("string") .def( "find", &std::string::find ) ;
I don't expect this to compile, much less execute with expected results.
I realize this may be a "newbie" (which I am) question. I have been scanning the extensive documentation, but it's not yet coming together in my head.
You can write "thin wrapper functions" which you can expose. For example: long string_find(std::string& self, python::str sub, long start, long end) { ... } class_std::string("string") .def("find", string_find) ... ; You might find it useful to us a first argument of type python::back_referencestd::string&. From this class you can get the std::string object and the Python object which contains it, so, for example, assuming you had written a __getslice__ method, you could slice the object itself and search in that: long string_find( python::back_referencestd::string& self , python::str sub , long start , long end) { std::string& me = self.get(); // get the string object object sliced = self.source().slice(start,end); // do something with sliced. ... } But then again, this migh be more complication than you really need. HTH, -- David Abrahams dave@boost-consulting.com * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution
participants (2)
-
Bruce Lowery <bruce_lowery@yahoo.com>
-
David Abrahams