简体   繁体   中英

SWIG LUA C++ wrapper

I am new to SWIG and I am trying some tutorials but running into compilation issues.

The functions I am trying to wrap (ex.cxx):

 #include <time.h>
 double My_variable = 3.0;
 
 int fact(int n) {
     if (n <= 1) return 1;
     else return n*fact(n-1);
 }
 
 int my_mod(int x, int y) {
     return (x%y);
 }
    
 char *get_time()
 {
     time_t ltime;
     time(&ltime);
     return ctime(&ltime);
 }

the SWIG wrapper definition (ex.i):

%module ex
 %{
 /* Put header files here or function declarations like below */
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();
 %}
 
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();

the minimal setup to call the wrappers (min.cxx):

#include <stdio.h>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <string.h>
//#include "ex_wrap.cxx"

extern "C" {
extern int luaopen_ex(lua_State* L); // declare the wrapped module
}

int main(int argc,char* argv[]) {
  char buff[256];
  int error;
    
  lua_State *L;
  if (argc<2) {
    printf("%s: <filename.lua>\n",argv[0]);
    return 0;
  }
  L=luaL_newstate();    // https://stackoverflow.com/questions/8552560/embedding-lua-in-c
  luaL_openlibs(L); // load basic libs (eg. print)
  luaopen_ex(L);    // load the wrappered module
  if (luaL_loadfile(L,argv[1])==0) // load and run the file
    lua_pcall(L,0,0,0);
  else
    printf("unable to load %s\n",argv[1]);
  /*while (fgets(buff, sizeof(buff), stdin) != NULL) {
    error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
            lua_pcall(L, 0, 0, 0);
    if (error) {
      fprintf(stderr, "%s", lua_tostring(L, -1));
      lua_pop(L, 1);  // pop error message from the stack
    }
  }*/
    
  lua_close(L);
  return 0;
}

and the compile commands:

swig -debug-symtabs -debug-symbols -debug-csymbols -o ex_wrap.cxx -c++ -lua ex.i 
clang -std=c++11 -I/usr/local/include/lua -c min.cxx -o min.o
clang -std=c++11 -fvisibility=default -I/usr/local/include/lua -c ex_wrap.cxx -o ex_wrap.o
clang -std=c++11 -c ex.cxx -o ex.o
clang -std=c++11 -I/usr/local/include/lua -L/usr/local/lib/lua -llua ex_wrap.o min.o ex.o -o mylua
clang -shared -std=c++11 -I/usr/local/include/lua -L/usr/local/lib/lua -llua min.o ex.o -o ex.so

The last command fails with

Undefined symbols for architecture x86_64:
  "_luaopen_ex", referenced from:
      _main in min.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

luaopen_ex() is defined in the ex_wrap.cxx generated by the swig command, but the linker cannot seem to find it. BTW, if I include ex_wrap.cxx directly into min.cxx, it compiles and I can run Lua code with this mini interpreter afterwards. Any ideas, thank you.

it's a linking failure error, and it happens because it can't link luaopen_example , but why it happens? luaopen_example is to load the wrapped module as you mentioned and it's named "example" only if the module name is the same.

in swig and lua wrapper, the wrapper name depends on the file to be wrapped name, but if you don't want to go this way, you can use the option -o , then the wrappered module will export one function "int luaopen_example(lua_State* L)" which must be called to register the module with the Lua interpreter. The name "luaopen_example" depends upon the name of the module.

so i suggest you just keep the name of the wrapper derived from the module, or you can adjust the loading function luaopen_xxxx to your wrapper name.

for full resource you can take a look at SWIG and Lua

luaopen_example is defined in an extern "C" {} block in ex_wrap.cxx , but compiling ex.c with g++ declares luaopen_example as a C++ function, so the linker looks for a C++ mangled name to resolve luaopen_example(lua_State*) and not simply luaopen_example

Change your declaration in ex.c to

extern "C" {
 extern int luaopen_example(lua_State* L); // declare the wrapped module
}

and the code will compile.

( You might be also be interested in the answer to this question, which explains name mangling: What is the effect of extern "C" in C++? )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM