1

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.

1 Answer 1

1

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);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

@Devian - Thank you very much for your code sample, it works well in my 32 and 64-bit builds. Two other build types are 32-bit and 64-bit wide character builds. For the wide character builds, I need to include both the std_wiostream.i and std_wsstream.i files in my Interface file for SWIG. When I include these file I get extraneous SWIG statements included in the wrap file. These statements are of the form: if (SWIG_IsNewObj(res2)) delete arg2; The statements cause compiler errors because the variable res2 does not exist. Any idea why these lines are being inserted in the wrapper file?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.