Timothy Fisher
Timothy Fisher

Reputation: 93

Converting Strings in Linux using SWIG for Python

I have a C++ class that is able to output strings in normal ASCII or wide format. I want to get the output in Python as a string. I am using SWIG (version 3.0.4) and have read the SWIG documentation. I'm using the following typemap to convert from a standard c string to my C++ class:

%typemap(out) myNamespace::MyString &
{
    $result = PyString_FromString(const char *v);
}

This works fine in Windows with the VS2010 compiler, but it is not working completely in Linux. When I compile the wrap file under Linux, I get the following error:

error: cannot convert ‘std::string*’ to ‘myNamespace::MyString*’ in assignment

So I tried adding an extra typemap to the Linux interface file as so:

%typemap(in) myNamespace::MyString*
{
    $result = PyString_FromString(std::string*);
}

But I still get the same error. If I manually go into the wrap code and fix the assignment like so:

arg2 = (myNamespace::MyString*) ptr;

then the code compiles just fine. I don't see why my additional typemap isn't working. Any ideas or solutions would be greatly appreciated. Thanks in advance.

Upvotes: 1

Views: 473

Answers (1)

Devan Williams
Devan Williams

Reputation: 1417

It doesn't look like your typemap is using the arguments quite correctly. You should have something like this instead:

%typemap(out) myNamespace::MyString &
{
    $result = PyString_FromString($1);
}

Where the '$1' is the first argument. See the SWIG special variables for more information [http://www.swig.org/Doc3.0/Typemaps.html#Typemaps_special_variables]

EDIT:

To handle the input typemap, you will need something like this:

%typemap(in) myNamespace::MyString*
{
    const char* pChars = "";
    if(PyString_Check($input))
    {
        pChars = PyString_AsString($input);
    }
    $1 = new myNamespace::MyString(pChars);
}

You can do more error checking and handle Unicode with the following code:

%typemap(in) myNamespace::MyString*
{
    const char* pChars = "";
    PyObject* pyobj = $input;
    if(PyString_Check(pyobj))
    {
        pChars = PyString_AsString(pyobj);
        $1 = new myNamespace::MyString(pChars);
    }
    else if(PyUnicode_Check(pyobj))
    {
        PyObject* tmp = PyUnicode_AsUTF8String(pyobj);
        pChars = PyString_AsString(tmp);
        $1 = new myNamespace::MyString(pChars);
    }
    else
    {
        std::string strTemp;
        int rrr = SWIG_ConvertPtr(pyobj, (void **) &strTemp, $descriptor(String), 0);
        if(!SWIG_IsOK(rrr))
            SWIG_exception_fail(SWIG_ArgError(rrr), "Expected a String "
        "in method '$symname', argument $argnum of type '$type'");
        $1 = new myNamespace::MyString(strTemp);
    }
}

Upvotes: 1

Related Questions