简体   繁体   English

SWIG LUA C++ 包装

[英]SWIG LUA C++ wrapper

I am new to SWIG and I am trying some tutorials but running into compilation issues.我是 SWIG 的新手,我正在尝试一些教程,但遇到了编译问题。

The functions I am trying to wrap (ex.cxx):我试图包装的功能(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): SWIG 包装器定义(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):调用包装器的最小设置(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. luaopen_ex() 是在 swig 命令生成的 ex_wrap.cxx 中定义的,但是 linker 似乎找不到它。 BTW, if I include ex_wrap.cxx directly into min.cxx, it compiles and I can run Lua code with this mini interpreter afterwards.顺便说一句,如果我将 ex_wrap.cxx 直接包含到 min.cxx 中,它会编译,之后我可以使用这个迷你解释器运行 Lua 代码。 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 ,但为什么会发生呢? luaopen_example is to load the wrapped module as you mentioned and it's named "example" only if the module name is the same. luaopen_example将加载您提到的包装模块,并且仅当模块名称相同时才将其命名为“example”。

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. 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)" 必须调用它来向 Lua 解释器注册模块。 The name "luaopen_example" depends upon the name of the module.名称“luaopen_example”取决于模块的名称。

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.所以我建议你只保留从模块派生的包装器的名称,或者你可以将加载 function luaopen_xxxx调整为你的包装器名称。

for full resource you can take a look at SWIG and Lua如需完整资源,您可以查看SWIG 和 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 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将您在ex.c中的声明更改为

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++? ) (您可能也对这个问题的答案感兴趣,它解释了名称修饰: What is the effect of extern "C" in C++?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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