c++luaswigtypemaps

How to wrap a C++ function that uses referenced custom type in SWIG?


first of all, I could wrap my C++ function which uses my custom string type. Here's how I did it.

This is my C++ function.

static void my_func(t_string message) {
    do_something(message.c_str());
}

And this is the SWIG typemap.

%typemap(in) (t_string message)
{
    if (!lua_isstring(L, 1)) {
      SWIG_exception(SWIG_RuntimeError, "argument mismatch: string expected");
    }
    $1 = lua_tostring(L, 1);
}

While this seems to work fine, I wonder if it's possible to wrap my_func(t_string &message) or my_func(const t_string &message).

The reason I'm asking this is because I think passing string by a reference would be a little faster than pass by value since I can avoid copying the string unnecessarily.

Please let me know if I'm wrong about this.


Solution

  • One thing ahead: I don't think it is worth the trouble to pass by reference for an extra bit of performance, because the overall performance will probably be dominated by the conversion between interpreter types and C++ types. Furthermore you might actually not gain any performance thanks to today's move semantics, cf. Are the days of passing const std::string & as a parameter over?

    SWIG treats references as pointers and initializes them to nullptr. That means you have to new up a string, store it in the argument and define an extra freearg typemap to get rid of the allocated memory again.

    %module references
    
    %{
    #include <iostream>
    #include <string>
    
    using t_string = std::string;
    
    static void my_func(const t_string &message) {
        std::cout << message << '\n';
    }
    %}
    
    %include "exception.i"
    
    %typemap(in) (const t_string &message)
    {
        if (!lua_isstring(L, 1)) {
          SWIG_exception(SWIG_RuntimeError, "argument mismatch: string expected");
        }
        $1 = new t_string{lua_tostring(L, 1)};
    }
    
    %typemap(freearg) (const t_string &message)
    {
        delete $1;
    }
    
    void my_func(const t_string &message);