lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I have just started working on a new project using C++ and LuaJIT (and also
just started using Lua/LuaJIT) and I wanted to confirm some questions about
the best way of setting up the bindings between the two. 

I'm currently not using any existing binding libraries/tools as I couldn't
find one I liked and that used the FFI. If I've missed one please let me
know.
My current approach is to run my binding generator before compilation and
generate a cpp + lua binding file. 
I use clang to visit each method and output the corresponding wrapper
function.

For example, for the input:

   class Test1 {
   public:
      void Method1(const char *text);
   };

   class Test2 {
   public:
      void Method1(Test1 *a, int b);
   };

   class Test3 : public Test2 {
   public:
      void Method2();
   };


I would generate a wrapper file for the C++:

   Test1 * Test1_new() {
      return new Test1();
   }
   void Test1_delete(Test1 *__this) {
      delete __this;
   }
   void Test1_Method1(Test1 *__this, const char *text) {
      __this->Method1(text);
   }
   void Test2_Method1(Test2 *__this, Test1 *a, int b) {
      __this->Method1(a, b);
   }
   void Test3_Method2(Test3 *__this) {
      __this->Method2();
   }

and then a Lua file:

   ffi = require('ffi')
   ffi.cdef[[
      typedef struct { void *__this; } Test1;
      typedef struct { void *__this; } Test2;
      typedef struct { void *__this; } Test3;

      Test1 *Test1_new();
      void Test1_Method1(void *__this, const char *text);
      void Test2_Method1(void *__this, void *a, int b);
      void Test3_Method2(void *__this);
   ]]
   C = ffi.C

   local Test1_index = {Method1 = function(__this, text)
C.Test1_Method1(__this, text) end }
   local Test1_mt = ffi.metatype("Test1", { __index = Test1_index})
   Test1 = function() return Test1_mt(C.Test1_new()) end

   local Test2_index = {Method1 = function(__this, a, b)
C.Test2_Method1(__this, a, b) end }
   local Test2_mt = ffi.metatype("Test2", { __index = Test2_index})
   Test2 = function() return Test2_mt(C.Test2_new()) end

   local Test3_index = CopyTable({Method2 = function(__this)
C.Test3_Method2(__this) end }, Test2_index)
   local Test3_mt = ffi.metatype("Test3", { __index = Test3_index})
   Test3 = function() return Test3_mt(C.Test3_new()) end


(In my case I delete/free the objects in C++ so I don't have to worry about
gc for most of the classes)
I'm also making sure that none of the C++ classes I expose use multiple
inheritance to simplify things, and I currently use void * in the ffi cdef
so I don't have casting issues.
I can also generate non ffi bindings in a similar fashion.

I know the above works as I have it working, but I'm not sure if I've missed
something or if there is a faster/easier/better way of doing things? 

Thanks,
Steven