This is an interesting tip. It shows the recipe for writing a DLL in native C/C++ can be called from Lua. Warning you’ll need to be comfortable with low level C/C++ for this to be of use to you. The good thing is the C is the linga-franca for computer operating systems – once you can get to C you can get to anything. This documentation here makes it possible to integrate any 3rd party Lua extension library into Iguana whenever you need it.
You can do this from any platform – Windows 32 and 64 bit but one thing to make sure of is that if you are using the 32 bit version of Iguana that you compile a 32 bit extension DLL. Likewise if you are using the 64 bit version of Iguana that you compile a 64 bit extension DLL. You can see what type of Iguana instance you are running from the version stamp. Here we show the recipe for Windows.
The same can be done on Linux or Mac OS X using this makefile and you’ll also need this hello.exports_list file which is used to make a file which restricts what exports you should see. If you have successfully built the hello.so under Mac OS X you should see something like this when you do nm hello.so.
Here’s the recipe:
- Download and install the nightly snapshot. This recipe requires Iguana 5.6 and above. Iguana 5.6 is due out around the end of November 2013.
- Download and unzip this hello.zip with the source code.
- Set up a command line prompt that has been set up to allow command line compiles with Visual Studio. There are batch files which ship with Visual Studio to do this. Sometimes there are menu options to open up a command line prompt in this manner. Pay attention as to whether you want a 32 bit or 64 bit build. It must match with the version (32/64 bit build) of Iguana you are using. This screenshot might be helpful.
- Run build.bat at the command line.
- This should create a DLL called ‘hello.dll’.
- Copy this hello.dll into the working directory of Iguana.
- Then run this Lua script:
require("hello") function main() local avg, sum = hello.compute_average_and_sum(100.5, 29.5) print("avg = " .. avg) print("sum = " .. sum) hello.world("Foo") end
It shows a couple of example functions.
There is also an example Visual Studio 6.0 workspace hello.dsw and project file which will compile the same hello.dll.
How does it work?
In Iguana 5.6 we changed the way we link the Lua libraries into Iguana. We statically link Lua into the core iguana.exe binary itself. Then we export the Lua API using plain C linkage from the iguana.exe. You can see how this works if you run dumpbin /exports iguana.exe. This is different to how Iguana 5.0 and 5.5 link to Lua. We changed things to make it easy to make modules just like this.
One helpful diagnostic that you can run over your hello.dll on windows is to use the dumpbin utility. This can be helpful in verifying that you have compiled a 32 bit or a 64 bit DLL. In this subpage I have shown the dumpbin output for a 32 and a 64 bit version of hello.dll.
The beauty of this linking approach is that DLLs compiled for older versions of Iguana should still work for newer versions of Iguana.
Here’s a summary of the files in the zip:
|iguana_lua_export.def||This “def” file is compiled into an import library. It lists off all the symbols that are exported by iguana.exe.|
|lua.h, luaxlib.h, luaconf.h||These 3 header files which give the functions that are part of the Lua API. These files came from (http://www.lua.org/ftp/lua-5.1.4.tar.gz) to match the version of Lua that Iguana uses. You shouldn’t edit these but they will be included by your extension DLL.|
|hello.cpp||This contains two example functions. For more information on how to extend this and use the Lua API, look at the Lua reference manual which describes the API very well.|
|hello.dsp, hello.dsw||Optional Visual Studio 6.0 workspace and project file. This is another way of compiling the hello.dll.|
With great power comes great responsibility. If you have code inside your DLL which causes an access violation, assert etc. you can bring down Iguana.
Another thing to watch out for is how your code handles C++ exceptions. You should catch these inside your own native code and not let them propagate back into Iguana.
Because Iguana runs each translator on its own thread one issue your C++ extension DLL will need to handle correctly is thread safety. That can be done in a variety of ways. Some legacy code might need to have a global mutex around the code if it was not designed to be thread safe. Newer code can be made thread safe by avoiding global and static variables.
If you have more questions please feel free to ask us about it.
One of our users kindly figured out how to do the same with C#, see this forum: