如何使用静态C ++库扩展Lua? [英] how do I extend Lua with a static c++ library?

查看:132
本文介绍了如何使用静态C ++库扩展Lua?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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\

我的Lua脚本:

foo.bar()

我的lua_foo.h文件:

#include <lua.h>
extern "C" int luaopen_foo( lua_State* L );

我的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;
}

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

有人可以帮助我了解我要去哪里哪里吗?谢谢.我宁愿避免使用c ++包装器(目前),也不想将此库打包为与Lua主引擎分离的DLL.


编辑

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

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 );
}

解决方案

重要的是要了解require机制的工作原理以及代码为何不起作用.

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

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

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

简单地调用luaopen_foo将会不执行任何操作.确实,简单地调用此函数是一个坏主意.它是一个Lua函数,需要被称为作为Lua函数(即:您需要使用lua_pushcfunction将其推入Lua堆栈,并使用lua_call进行调用,依此类推). /p>

如果要创建一个 local 模块(一个不在Lua脚本或DLL中,而是从代码中公开的模块),则需要使用Lua工具来执行此操作.具体来说,请使用luaL_requiref:

luaL_requiref(L, "foo", luaopen_foo, 0);

调用此函数,而不是直接调用luaopen_foo.这将自动将luaopen_foo中的返回值注册到require的已加载模块的内部数据库中.因此,随后对require "foo"的调用将返回此表.

另一件事:do是Lua中的关键字;您不应该为Lua表键名使用关键字.您可以 ,但是您始终必须引用它们(即:您的脚本必须执行foo["do"](...)才能调用它).

I have a Visual Studio 2008 C++03 application that uses Lua 5.2.1. I would like to extend Lua with a module called "foo", but when I call require("foo") in my Lua script, I get the error:

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\

My Lua script:

foo.bar()

My lua_foo.h file:

#include <lua.h>
extern "C" int luaopen_foo( lua_State* L );

My lua_foo.cpp file:

#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;
}

These are compiled in to a static library "lua_foo.lib" which is statically linked to my main Lua executable.

Can anybody help me understand where I'm going wrong? thanks. I would prefer to avoid c++ wrappers (for now) and I do not want to package this library as a separate DLL from the main Lua engine.


EDIT

The issue was in the lua engine code. I added the luaL_requiref per @NicolBolas 's suggestion.

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 );
}

解决方案

It's important to understand how the require machinery works and therefore why your code doesn't.

require is designed to look for Lua scripts in the file system and DLLs. Static libraries are not DLLs; indeed, as far as C/C++ is concerned, once you've finished linking, static libraries are no different than compiling those .c/.cpp files into your application directly.

When require finds a DLL with the appropriate name, it loads it and attempts to find a function named luaopen_<modname>, where <modname> is the name of the module. When it does, it will execute this function and store the value it returns in an internal database of loaded modules.

Calling require for a module will return whatever this function returned; if the module has already been loaded, then the return value is pulled from the database and returned directly.

Simply calling luaopen_foo will not do any of this. Indeed, simply calling this function is a bad idea; it is a Lua function and needs to be called as a Lua function (ie: you need to push it onto the Lua stack with lua_pushcfunction and call it with lua_call and so forth).

If you want to create a local module (one not in a Lua script or DLL, but exposed from your code), then you need to use the Lua facilities to do that. Specifically, use luaL_requiref:

luaL_requiref(L, "foo", luaopen_foo, 0);

Call this instead of calling luaopen_foo directly. This will automatically register the return value from luaopen_foo with require's internal database of loaded modules. Thus, subsequent calls to require "foo" will return this table.

One more thing: do is a keyword in Lua; you should not use keywords for Lua table key names. You can, but you always have to quote them (ie: your script must do foo["do"](...) to call it).

这篇关于如何使用静态C ++库扩展Lua?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆