I closed off my last post about adding Lua to an SDL application saying I’d look at a tool to do the bindings for me. I actually already had something in mind for the job. I looked at a couple but SWIG seems to be the most versatile. It’s not tied just to Lua so the work I put in to learning how to use SWIG will also apply partly to any other scripting languages I want to support. Any within the realm that SWIG supports, of course. Notably missing from the list so far is Javascript. Scheme is represented in the form of Guile (which is a specific Scheme interpreter as far as I understand).
The documentation for SWIG is pretty sizable but of course with all the combinations of host & script language out there they aren’t all explained clearly enough for a beginner like me. So I started to experiment. SWIG focuses on wrappers for C, C++ support seems more complex. So to understand things I had to scale back even from my simple SDL C++ test program then scaled back up once I got some communication between code written in both languages.
What I came up with was that I had to write a separate interface file (SimpleGraphics.i) then use swigwin to read that file and create a wrapper for my class. The wrapper gets the default name of SimpleGraphics_wrap.cxx. I added the wrapper file as a source file in my Visual Studio project then the wrapper gets compiled with the rest of the project.
Here's the header for the class in question
Based on the simple examples in the SWIG tutorial (I count myself in the truly lazy), I had hoped I could just include the header in the interface file (SimpleGraphics.i) like the following.
This did not work. I tried a lot of variations on that theme but got nowhere with it. What did work was copying the contents of the header to the interface (that is from SimpleGraphics.h to SimpleGraphics.i) and using the %inline directive. My current version of SimpleGraphics.i looks like this.
I dropped all the private stuff that SWIG can't use anyway and I added a typedef for the Uint8 type that I use from SDL. Without the %inline the default directive is %header. According to the docs
The %inline directive inserts all of the code that follows verbatim into the header portion of an interface file. The code is then parsed by both the SWIG preprocessor and parser.
Since the interface is copied from the header and the wrapper is created from the interface, it's important to remember that every time the header changes (that is, the interface to the class changes) the SWIG interface file has to be adjusted accordingly and the wrapper has to be created again using swigwin. In a real project, these steps could be at least partially automated in the build process.
The command line I used for swigwin was roughly
This allowed me to run the a little Lua script that draws a line with the SimpleGraphics::DrawLine () method.