如何使用静态c ++库扩展Lua?

Pau*_*ulH 5 c++ lua

我有一个使用Lua 5.2.1的Visual Studio 2008 C++ 03应用程序.我想用一个名为"foo"的模块扩展Lua,但是当我调用require("foo")我的Lua脚本时,我得到错误:

foo_test.lua:1: module 'foo' not found:
    no field package.preload['process']
    no file '!\lua\process.lua'
    no file '!\lua\process\init.lua'
    no file '!\process.lua'
    no file '!\process\
Run Code Online (Sandbox Code Playgroud)

我的Lua脚本:

foo.bar()
Run Code Online (Sandbox Code Playgroud)

我的lua_foo.h文件:

#include <lua.h>
extern "C" int luaopen_foo( lua_State* L );
Run Code Online (Sandbox Code Playgroud)

我的lua_foo.cpp文件:

#include "lua_foo.h"
#include <lua.hpp>

static int l_bar( lua_State *L )
{
    puts( "in bar()" );
    return 1;
}

int luaopen_foo( lua_State *L ) 
{
    static const luaL_Reg foo[] = {
        { "bar", l_bar },
        { NULL, NULL }
    };

    luaL_newlib( L, foo );
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

这些编译成静态库"lua_foo.lib",它静态链接到我的主Lua可执行文件.

任何人都可以帮我理解我哪里出错了吗?谢谢.我宁愿避免使用c ++包装器(现在),我不想将这个库打包为主Lua引擎的单独DLL.


编辑

问题出在lua引擎代码中.我添加了luaL_requiref@NicolBolas的建议.

lua_State* L = luaL_newstate();
if( NULL != L )
{
    luaL_openlibs( L );
    luaL_requiref( token.get(), "foo", luaopen_foo, 1 );
    luaL_dofile( L, "foo_test.lua" );
    lua_close( L );
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 9

了解require机器的工作原理以及代码没有的原因非常重要.

require旨在查找文件系统和DLL中的Lua脚本.静态库不是DLL; 实际上,就C/C++而言,一旦完成链接,静态库与直接将这些.c/.cpp文件编译到应用程序中没有什么不同.

require找到具有适当名称的DLL时,它会加载它并尝试查找名为的函数luaopen_<modname>,其中<modname>是模块的名称.如果是这样,它将执行此函数并将其返回的值存储在已加载模块的内部数据库中.

调用require模块将返回此函数返回的内容; 如果模块已经加载,则从数据库中提取返回值并直接返回.

简单的调用luaopen_foo不会做任何的这个.实际上,简单地调用这个函数是个坏主意; 它是一个Lua函数,需要被称为Lua函数(即:你需要将它推到Lua堆栈上lua_pushcfunction并用它来调用它lua_call等等).

如果要创建本地模块(一个不在Lua脚本或DLL中,但从代码中公开),那么您需要使用Lua工具来完成此操作.具体来说,使用luaL_requiref:

luaL_requiref(L, "foo", luaopen_foo, 0);
Run Code Online (Sandbox Code Playgroud)

调用此而不是luaopen_foo直接调用.这将自动地从寄存器返回值luaopen_foorequire的加载的模块的内部数据库.因此,后续调用require "foo"将返回此表.

还有一件事:do是Lua中的关键字 ; 您不应该为Lua表键名使用关键字.你可以,但你总是要引用它们(即:你的脚本必须foo["do"](...)要调用它).

  • @Mud:不,这很重要.你*不能直接调用`luaopen_base`或类似的Lua库打开函数.Lua的文档非常清楚***.在5.1中,[它表示你不能直接称它](http://www.lua.org/manual/5.1/manual.html#5).在5.2中,[它具体说通过`luaL_requiref`来调用它们](http://www.lua.org/manual/5.2/manual.html#6). (2认同)
  • @Mud:源代码是什么并不重要; Lua文档说*不*直接调用它们.如果您想与Lua文档争论,请随意.我只是说*它*说的是什么.另外,当我直接打电话给'luaopen_base`时,Lua 5.1曾经撞到我身上; 这就是我知道规则的原因. (2认同)