2009-08-15 211 views
4

我目前正在实施的Lua成我工作的一个应用程序。目前我只使用C api并使用lua_register注册函数,但我希望能够将静态和非静态函数指针传递给某些类方法。Lua脚本执行

我发现在网络上某些库,但因为我需要很少的整体功能他们提供我在想,如果有一个简单的方法来做到这一点。

谢谢。

+0

你实际上有什么问题lua_register?它是否被宣布为staric的函数的可见性? – 2009-08-17 09:30:06

回答

4

复杂库API通常可以迅速包裹和(几乎)完全使用SWIG。在这种情况下使用SWIG的一个优点是,构建基于SWIG的包装器很容易,可以使用包括Lua,Perl,Python,Ruby和Java等在内的18 major languages库。

如果Lua是您首选的(也可能是唯一的)关注点,那么我建议学习使用luaL_register()作为策略的核心,在C中构建Lua模块。以这种方式构建模块的优点是您可以保留所有的功能都在一个名字空间中,没有任何开销。你将需要制作一个匹配Lua C函数调用约定的包装函数(就像你使用lua_register()一样),并从栈中收集Lua参数,调用包装函数,并将任何返回值和出参数推回到Lua堆栈。关于如何去做的一个很好的概述可以在Lua的Programming中找到。第一版的在线副本在Chapter 26中讨论了库创建,但是是为Lua 5.0编写的。我强烈要求任何人认真使用Lua拥有当前版本的PiL的副本。

不幸的是,Lua 5.1与5.0最大的区别在于模块(C和Lua)的动态加载与require

下面是一个C库,在Lua 5.1工作的完成(如果小)的例子。我们先从包装的C文件的执行情况:特别

#include <lua.h> 
#include <luaxlib.h> 
#include <math.h> 
#undef PI 
#define PI (3.14159265358979323846) 

static int l_sin (lua_State *L) { 
    double r = luaL_checknumber(L,1); 
    lua_pushnumber(L, sin(r)); 
    return 1; 
} 

static int l_cos (lua_State *L) { 
    double r = luaL_checknumber(L,1); 
    lua_pushnumber(L, cos(r)); 
    return 1; 
} 

static const struct luaL_reg smlib [] = { 
    {"sin", l_sin}, 
    {"cos", l_cos}, 
    {NULL, NULL} /* sentinel */ 
}; 

int luaopen_sm (lua_State *L) { 
    luaL_openlib(L, "sm", smlib, 0); 
    lua_pushnumber(L,PI); 
    lua_rawset(L,-2,"pi"); 
    return 1; 
} 

注意,需要导出的唯一功能是luaopen_sm(),其名称必须与将与require使用的模块的名称以及DLL文件的名称。编译为一个名为sm.dll的DLL文件(可能命名的类Unix系统libsm.so),那么它可以被加载并在一个Lua脚本中使用这样的:

 
require "sm" 
print(sm.sin(sm.pi/3), sm.cos(sm.pi/3)); 

这个例子,虽然未经测试,应该编译跑。有关从math.h包装大多数函数的完整示例,请参阅随Lua分发的source to the math module。由于这些薄包装包含大量重复代码,因此只有每个函数声明时,SWIG等工具才能创建它们。

C++类的包装方法在原则上是相似的。每个的Lua-调用包装函数将要需要,可以在C++侧被映射到this一个参数,它必须被实现为一个模块静电功能或静态成员函数也定位目标对象实例以及转换其他论点。 SWIG在构造这种包装材料方面特别擅长,并且沿途隐藏了许多血管细节。