1、本文将继续讲解在Lua Code中调用注册的C函数.偶在学习本文知识点时,由于知识点的遗漏,在这个上面浪费了大量时间和精力。一直都没有没明白,Lua 通过面向对象的方式是如果调用注册的C函数。在Programming In Lua一书,有对这个方面的讲解。但是当时看书,就是不理解。因为在前面的章节中,有一个重要的知识点被遗漏。在Lua 元方法中,有两个特别重要的.__index 和__newindex被我遗漏。这两个元方法特别重要,对于定义和拓展Lua的机制,基本依靠这两个。
2、本文首先由Lua Code中对__index 和__nexindex 的讲解引入,来对通过Lua Code 面向对象调用注册的C函数。
2.1 在Lua Code中讲解metatable中__index和__newindex两个重要的元方法
2.2 注册C模块
2.3 通过Lua Code面向对象调用注册的C函数。
3、本文作为在Lua 中实现面向对象编程和在Lua中绑定C++对象的一个铺垫。在Lua的演化中,作者并没有把面向对象特点加入的Lua的语言中,但是,一个语言的发展深入当时环境的影响,Lua在发展时,由用户的原因,被迫满足在Lua中提供面向对象的需求。在Lua中实现面向对象只要依靠Table和metatable两个机制,来实现面向对象的形式。
4、本文不是详细讲解Lua 编写语言的知识点,但是会总结关键知识点。对于Lua本身的学习,主要Programming In Lua 和Lua Reference Manual 足以.
5.1 下面LuaCode将讲解元方法和Lua Code中实现面试对象调用:
object ={}
methodTab ={}
setmetatable(object, methodTab)
methodTab.__tostring=function()
print("object tostring...")
return "object"
end
methodTab.__call=function()
print("object call...")
end
methodTab["method"]=function()
print("object method...")
return "object method"
end
object() --对Table进行函数调用,对于__call 元函数
tostring(object)
print(object)
<span style="color:#ff0000;">methodTab.__index =methodTab --__index元方法表示对Object Table的进行定义.当调用Object["method"]获取Object指定键操作时,如果Object中不存在指定键,</span><span style="color:#ff0000;">则在查询Object是否存在metatable,如果存在metatable则在metatable中查询指定键元素。</span> local m =object["method"] print(m) m()
<pre name="code" class="plain">object["method"]()由于在忽悠__index 和__nexindex知识点,在后来的学习中,总是理解不清楚,浪费了大量的时间。在此特别罗列出知识点,希望能够减少读者在错误的道路上浪费的时间。
5.2 下面例子代码来自于Programming In Lua的章节中。来讲述注册C模块和通过Lua面向对象调用注册的C函数。在Lua中面向对象调用,实际是Lua作者不想把面向对象机制引入Lua语言本身,导致语言复杂性,而引入一种语法糖来实现面向对象调用。在Lua作者的文章中多次提及Lua语言本身不提供面向对象机制,但是提供对面向对象的支持。
后面的文章会继续设计Lua的面向对象东东,包括对Lua作者面向对象观点的翻译。
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <stdio.h>
#define CnExampleStr "example"
//在C语言中的结构体,绑定到Lua语言中
typedef struct
{
int Val;
int Open;
} ExampleType, * ExamplePtrType;
static ExamplePtrType LclExamplePtrGet(lua_State *L,int StkPos)
{
ExamplePtrType ExamplePtr = (ExamplePtrType)luaL_checkudata(L, StkPos, CnExampleStr);
if (! ExamplePtr->Open)
luaL_error(L, "attempt to use a closed " CnExampleStr);
return ExamplePtr;
}
static int LclExampleStr(lua_State *L)
{
ExamplePtrType ExamplePtr = (ExamplePtrType)luaL_checkudata(L, 1, CnExampleStr);
if (ExamplePtr->Open)
lua_pushfstring(L, CnExampleStr " (%d)", ExamplePtr->Val);
else lua_pushfstring(L, CnExampleStr " (%d, closed)", ExamplePtr->Val);
return 1;
}
//获取c结构体数据
static int LclExampleGet(lua_State *L)
{
ExamplePtrType ExamplePtr = LclExamplePtrGet(L, 1);
lua_pushnumber(L, ExamplePtr->Val);
printf("Retrieving value of " CnExampleStr " (%d)\n", ExamplePtr->Val);
return 1;
}
//设置c结构体数据
static int LclExampleSet(lua_State *L)
{
ExamplePtrType ExamplePtr = LclExamplePtrGet(L, 1);
int Val = luaL_checkint(L, 2);
printf("Setting value of " CnExampleStr " from %d to %d\n",
ExamplePtr->Val, Val);
lua_pushnumber(L, ExamplePtr->Val);
ExamplePtr->Val = Val;
return 1;
}
//关闭结构体
static int LclExampleClose(lua_State *L)
{
ExamplePtrType ExamplePtr = LclExamplePtrGet(L, 1);
printf("Closing " CnExampleStr " (%d) explicitly\n", ExamplePtr->Val);
ExamplePtr->Open = 0;
return 0;
}
//通过Lua Code构造C语言结构体
static int LclExampleOpen(lua_State *L)
{
//接受LuaCode传递参数
int Val = luaL_checkint(L, 1);
//申请由lua GC管理下的内存
ExamplePtrType ExamplePtr =(ExamplePtrType)lua_newuserdata(L, sizeof(ExampleType));
printf("Opening " CnExampleStr " (%d)\n", Val);
//设置数据
ExamplePtr->Val = Val;
ExamplePtr->Open = 1;
////在注册表中查询注册的C函数
luaL_getmetatable(L, CnExampleStr);
//设置userdata的CnExampleStr的metatable
lua_setmetatable(L, -2);
return 1;
}
void luaopen_register(lua_State *L)
{
static const luaL_reg regMethod[] =
{
{"open", LclExampleOpen},
{"close", LclExampleClose},
{"get", LclExampleGet},
{"set", LclExampleSet},
{"tostring", LclExampleStr},
{NULL, NULL}
};
//创建一个metatable用于标识userdata唯一性
luaL_newmetatable(L, CnExampleStr);
luaL_register(L,"ud_example",regMethod);
}
int main(int argc, char **argv)
{
/* initialize Lua */
lua_State* L = lua_open();
luaL_openlibs(L);
//luaopen_ud_example(L);
luaopen_register(L);
luaL_dofile(L, "sample_6.lua");
/* cleanup Lua */
lua_close(L);
return 1;
}print("sample_6.lua")
local ud1 =ud_example.open(1)
print(ud1)
print(ud_example.tostring(ud1))
local a =ud_example.get(ud1)
print("a:"..a)
local b =ud_example.set(ud1,2)
print("b="..b)到目前为止只要记住,Lua为了提高用户自定义数据类型,提供了userdata数据类型。userdata数据类型的生命周期由Lua GC管理。当userdata管理的C/C++对象时,当GC把userdata当做垃圾收集时,会调用__gc userdata的元方法。假如,C/C++对象生命周期由Lua GC管理,那么此时是释放C/C++对象的唯一机会。
本文中涉及到环境和userdata的如何使用?可以参考Lua Reference Manual .在本系列文章中,将会不断的讲解userdata的由来和使用方式方法。
本来本文应该完成第三部分,通过Lua Code面向对象语法糖调用注册的C函数,无奈,这内容比较多,涉及知识点较多。和老婆约好了,11点去同事家完,不想本文草草了事情,所以第三部以及涉及的知识点,将在下一张详细讲述。
Lua 与C/C++ 交互系列: Lua调用C/C++函数(4-1)
原文地址:http://blog.csdn.net/sunning9001/article/details/46580235