How to convert to std::string from python string in cython 0.20.2 and python3?

1,339 views
Skip to first unread message

Robert Ekendahl

unread,
Jul 1, 2014, 4:17:42 PM7/1/14
to cython...@googlegroups.com

Hi,

I posted a question over at stack overflow but figured I should ask it here as well. It feel like a somewhat basic question but I’m getting stuck so need some ideas for what to test.

You can see the answer at: http://stackoverflow.com/q/24518246/3757019

I’m posting the same info here:

I’m working on wrapping my first few C++ classes in Cython and was lucky to get through the first few simple ones. Now I’m getting a bad_ptr error in the constructor for a C++ class that takes in a std::string name argument. I have not been able to correctly figure out how to convert a Python string to a C++ std::string. Below is what I’m currently doing. What do I need to change?

For information I use latest cython 0.20.2, python 3.4 (32bit) on a Windows 7 machine and I use Visual Studio 2010 for compilation. I suspect the python 3.x could play into it since they have mucked with string definitions but I’m not sure how.

Here is the CPP Class definition I have:

    class HDMISOURCE_API Source: public TipInterface
    {
    public:
        Source(std::string name, Interface* env);
    ...

I want to expose this class to python through a cython class that simply takes in a name argument (and keeps the pointer internally).

Here is the relevant cython code I have:

    from libcpp.string cimport string

    cdef extern from "EnvironmentSelect.h":
        _TipUserEnvironmentInterface* _GetEnvironment "GetEnvironment" ()

    cdef extern from "HDMISource.h":
        cdef cppclass _HDMISource "HDMISource":
            _HDMISource(string, _TipUserEnvironmentInterface*) except +

    cdef class HDMISource:
        cdef _HDMISource* thisptr

        def __cinit__(self, string pin_map):
            env = _GetEnvironment()
            self.thisptr = new _HDMISource(pin_map, env)

        def __dealloc__(self):
            del self.thisptr

        def hello(self):
            print('HDMISource still says hello!')

To debug this I compile using Visual Studio 2010 and with debug flags. I then start python and from visual studio do attach to process. Then from the python prompt I do this:

    c:\Projects\psvm\python\tip>python
    Python 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 10:38:22) [MSC v.1600 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import tip
    >>> name = 'MyHDMITxPins'.encode('UTF-8')
    >>> type(name)
    <class 'bytes'>
    >>> hdmi = tip.HDMISource(name)

At this point I get a break point in the generated code (tip.cpp) and at that level the name is a std::basic_str with the correct value. I wonder if std::basic_str is what I want it to be though…

If I step through some of the code I arrive at the class I expect:

    HDMISource::HDMISource(std::string pinMap, TipUserEnvironmentInterface* env): TipInterface(pinMap, dynamic_cast<TipEnvironmentInterface*>(env)), m_videoFrameNum(0) 
    {
    ...
    }

But at this point the std::string PinMap reports as bad_ptr so somehow I’ve lost the string on my way down the hierarchy… (And I was so convinced it would be the other class pointer that would be the issue and it seem fine!).

If I let it run I get this in the python window:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "tip.pyx", line 60, in tip.HDMISource.__cinit__ (tip.cpp:1201)
        self.thisptr = new _HDMISource(pin_map, env)
    RuntimeError: Unknown exception
    >>>

It feels like I need to do something more in the cython code to convert to/from python string and std::str but I can’t figure out what. Please help! I will be forever grateful!


Robert Bradshaw

unread,
Jul 3, 2014, 12:23:11 PM7/3/14
to cython...@googlegroups.com
The conversion seems to be set up just fine. The only thought I had is
perhaps these take a std::string& rather than a std::string, in which
case bad things could happen when the original string gets reclaimed.
Reply all
Reply to author
Forward
0 new messages