c++luaswigtypemaps

How to create a SWIG typemap for functions that return specific type


I'm trying to create a SWIG typemap for functions that return specific type.

For example, this is my C++ function

t_float get()
{
    return 3.14159;
}

t_float is defined to either float or double depending on the #define setting on one header file. And it seems the SWIG i file cannot read the defined symbols in that file even when I include the header in i file.

So, I decided to create a typemap for this function so t_float type can be converted to lua_number.

But I have no idea how to create a typemap for functions that return a value.

I tried to do it myself but I couldn't make it.

%typemap(out) t_float
{
    lua_pushnumber(L, (lua_Number)($output));
}

How to correctly create a typemap so I can make get() return a number value in Lua?


Solution

  • This is a bit tricky. After pushing the result to the stack you also have to increase the number of return values which is stored in SWIG_arg. I only found out after I took a look at the internal typemaps of SWIG. (An identifier called $output doesn't exist).

    N.B.: Please immediately drop the habit of explicitly casting values to the desired type. This is dangerous because if the type does not match, you are telling the compiler “interpret this bit pattern as the desired type anyway, I know what I'm doing”. Just let the compiler do the implicit conversion for you. You will also receive a compiler error if the types are not convertible, which is much better than a segmentation fault or garbage values at runtime. See this Wandbox link for a demonstration and note that there are no compiler warnings!

    %module t_float
    %{
    typedef double t_float;
    t_float get() {
        return 3.14159;
    }
    %}
    
    %include <typemaps.i>
    
    %typemap(out) t_float {
        lua_pushnumber(L, $1);
        ++SWIG_arg;
    }
    
    t_float get();
    
    local t_float = require("t_float")
    print(t_float.get())