使用gcc编译lua的模块

时间:2012-09-16 07:15:09

标签: c++ c lua

我有以下用于测试的c ++代码:

#include <lua.hpp>
#include <iostream>

static int dummy(lua_State * L)
{
   std::cout << "Test";
   return 0;
} 

int luaopen_testlib(lua_State * L)
{
   lua_register(L,"dummy",dummy);
   return 0;
}

我用命令编译它,它没有给我任何错误:

g++  -Wextra -O2 -c -o testlib.o main.cpp
g++ -shared -o testlib.so testlib.o 

但是当我尝试在lua中加载它时,我得到了未定义的符号错误:

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> require"testlib"
error loading module 'testlib' from file './testlib.so':
./testlib.so: undefined symbol: _Z16lua_pushcclosureP9lua_StatePFiS0_Ei

对我来说,g ++命令中缺少一些内容,但我整个上午一直在寻找解决方案而无法通过这个简单的例子进行编译。

编辑:

经过几次重新编译后,它又回到了:

error loading module 'testlib' from file './testlib.so':
./testlib.so: undefined symbol: luaopen_testlib

通过添加:

解决了
extern "C" 
{
int luaopen_testlib(lua_State *L)
{
  lua_register(L,"dummy",dummy);
  return 0;
}
}

2 个答案:

答案 0 :(得分:3)

Lua 二进制文件被编译为 C 代码,库尝试将其用作 C++。这不会起作用,因为 C++ 会进行名称修改以支持重载。由于 C 不支持重载,因此不需要名称重整,也不会理解重整名称。

对此的解决方案是告诉 C++ 编译器它要与之交互的 Lua 函数是纯 C 语言,它们不需要名称修饰。

此外,luaopen_testlib 函数必须为 extern "C",因为它将从 C 代码中调用而不会进行修改。

extern "C" {
#include <lua.h>
}
#include <iostream>

static int dummy(lua_State * L)
{
    (void)L;
    std::cout << "Test"<<std::endl;
        return 0;
}

extern "C"
int luaopen_testlib(lua_State * L)
{
    lua_register(L,"dummy",dummy);
        return 0;
}

我使用 Lua 5.4.2 运行测试并使用以下命令构建库:

g++ -Wall -Wextra -O2 -Isrc -c -fPIC -o testlib.o testlib.cpp
g++ -shared -o testlib.so testlib.o

请注意,在我的测试设置中需要 -Isrc 才能找到 lua.h,而 -fPIC 需要在库中使用 cout(但可能 取决于使用的编译器版本)。

结果是:

Lua 5.4.2  Copyright (C) 1994-2020 Lua.org, PUC-Rio
> require 'testlib'
true    ./testlib.so
> dummy
function: 0x7ff07d2a0aa0
> dummy()
Test
> 

在这种情况下,使用的 Lua 版本没有任何区别。

答案 1 :(得分:0)

尝试使用Luabind。这是Hello World示例

#include <iostream>
#include <luabind/luabind.hpp>

void greet()
{
    std::cout << "hello world!\n";
}

extern "C" int init(lua_State* L)
{
    using namespace luabind;

    open(L);

    module(L)
    [
        def("greet", &greet)
    ];

    return 0;
}