This topic contains 10 replies, has 2 voices, and was last updated by  roho 2 years, 11 months ago.

Writing a native extension to Lua in C/C++ (and .NET…)

  • This is a new tip and trick in the wiki:

    It gives the recipe for doing an extension in C/C++ on Windows. The same can be done for Linux or Mac OS X. I’m curious to see how much interest there is in our user community to be able to do this.

    One neat thing about this is that it opens up the ability to access any low level API you can think of without us putting it in as a vendor.

    I’ve added a makefile that works for OS X into the wiki page. In theory it should work for Linux but it will probably require tweaking…

    It works fine with managed C++, too:

    1. In build.bat, I have added the compiler switch “/clr” (and removed “/EHsc /MT”, which are incompatible with this)
    2. In hello.cpp, I’ve added

    #using <mscorlib.dll>
    using namespace System;
    using namespace System::Runtime::InteropServices;

    3. Then I could call any .Net framework class, e.g.:

    String^ now = DateTime::Now.ToString();
    char *ansinow = (char *) Marshal::StringToHGlobalAnsi(now).ToPointer();
    lua_pushstring(L, ansinow);

    Oh that is pretty neat – I wasn’t subscribed to this thread.

    Hi, it’s me again, I just wanted to elaborate a bit on this solution.

    You can also link together a C# component and a C++/CLI component in one DLL, so the C# code can be called from Lua:

    • In build.bat, add the line
      csc /t:module foobar.cs
      This creates foobar.netmodule.
    • In the cl.exe line, add the switch “/FUfoobar.netmodule”. This enables the C# component to be used in the C++ code.
    • Add foobar.netmodule to the link.exe line, too.

    If you want to pass string parameters to C#, you must use Marshal::PtrToStringUni or one of its siblings. This is a bit tricky, but you can find examples in the Internet. Always keep in mind the correct string encoding!

    Nice – do you call C# libraries you have in production?

    Yes, there is a little snippet we have implemented in C# which we want to use in the Lua code, and this way works really fine. It’s only one class, but surely it would work with larger components, too.

    I have not tried it with the 64 bit version yet. If the DLL was compiled for “Any CPU”, it might just work – otherwise I’ll have to build a 64 bit version.

    I’d be surprised if you managed to have one binary for both 32 and 64 bit windows…

    What does the function do?

    I figured if I compile it with “Any CPU”, it should load into a 32 bit process or a 64 bit process, but I’ll see whether it works when I get my hands on a 64 bit machine. Otherwise, it would not be so tragic to have two versions, just a question to figure out the command-line switches in build.bat.

    Some of our input files have a signature, and the DLL checks whether the signature is correct.

    Today, I have tried this successfully with the 64 bit version, and I thought I’d share my findings.

    • The C++ components should be compiled and linked with the x64 version, e.g. under c:\Program Files\Microsoft Visual Studio 10.0\VC\bin\x86_amd64. You can also add a /machine:x64 command-line parameter.
    • C# components should not be compiled for the x64 platform. They should be AnyCPU. Otherwise, you will get a linker error LNK1302.
    • Then, the DLL compiled successfully, but it wouldn’t work. If in the translator I wrote require 'foo', I got the error message: “The specified module could not be found.” Using the Dependency Walker, I found out that the Visual C++ Redistributable was missing on the test machine. When I had installed it, all worked fine!

You must be logged in to reply to this topic.