Search code examples
c#c++stringswig

How to SWIG std::string& to C# ref string


I'm trying to convert a C++ function with std::string reference to C#.

My API looks like this:

void GetStringDemo(std::string& str);

Ideally I would like to see something like this from C#

void GetStringDemoWrap(ref string);

I understand I need to create a typemap for this, and I tried a few things by playing around with the std_string.i file, but I don't think I'm getting anywhere. Does anyone has any example. I'm new to both Swig and C# so I'm not able to come up with any genuine ideas.


Solution

  • Just in case somebody is looking for this in the future, I created std_string.i like this for C#. Seems to work for me. Note that I changed the ref to out since it was more appropriate in my case but ref should work as well.

    I called %include "std_string.i" from the .i file

    /* -----------------------------------------------------------------------------
     * std_string_ref.i
     *
     * Typemaps for std::string& and const std::string&
     * These are mapped to a C# String and are passed around by reference
     *
     * ----------------------------------------------------------------------------- */
    
    %{
    #include <string>
    %}
    
    namespace std {
    
    %naturalvar string;
    
    class string;
    
    // string &
    
    %typemap(ctype) std::string & "char**"
    %typemap(imtype) std::string & "/*imtype*/ out string"
    %typemap(cstype) std::string & "/*cstype*/ out string"
    
    //C++
    %typemap(in, canthrow=1) std::string &
    %{  //typemap in
        std::string temp;
        $1 = &temp; 
     %}
    
    //C++
    %typemap(argout) std::string & 
    %{ 
        //Typemap argout in c++ file.
        //This will convert c++ string to c# string
        *$input = SWIG_csharp_string_callback($1->c_str());
    %}
    
    %typemap(argout) const std::string & 
    %{ 
        //argout typemap for const std::string&
    %}
    
    %typemap(csin) std::string & "out $csinput"
    
    %typemap(throws, canthrow=1) string &
    %{ SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, $1.c_str());
       return $null; %}
    
    }
    

    The reason I need to define argout for const std::string& is because SWIG will get confused and override const std::string& also with the typemap. So I explicitly tell it not to override in my case (You may have a different use case)

    For Python I created something like this:

    %typemap(argout)std::string&
    {
        //typemap argout std::string&
        PyObject* obj = PyUnicode_FromStringAndSize((*$1).c_str(),(*$1).length());
    
        $result=SWIG_Python_AppendOutput($result, obj);
    }
    
    %typemap(argout) const std::string & 
    %{ 
        //argout typemap for const std::string&
    %}