Lua和so

ronald1年前职场8080

    实际在应用开发过程中,会用到很多第三方的库;Lua由于其易嵌入的特性,不仅可以使用Lua编写的库,也可以将C++的库进行二次封装供Lua调用。这里我们以实现在Lua中解析xml文件格式场景,结合C++编写的“tinyxml2” 这个库为例进行讲解:


库的准备及编译


第一步,下载“tinyxml2”的源码


下载链接:leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs. (github.com)

下载解压之后,主要就是三个文件:tinyxml2.cpp、tinyxml2.h;非常的轻量,先编译一波,看是否能编译通过

image-20220304153338948.png

第二步,如果对Lua版本有特殊要求的话,可以去Lua官网下载指定版本的lua源码


下载链接:Lua: download area


下载好源码之后,直接make就有liblua.a


库的封装及so的生成


有了“lua”和“tinyxml”的库之后,我们根据需求,基于“tinyxml”对其进行二次封装,这里我们想做的是把“xml”每个一级结构及其字段名和字段类型存入到全局表中;那么该怎么做呢?


假设我们的封装的so名字叫“libtinyxmllua.so”,我们得先定义接口“luaopen_libtinyxmllua”,并在“luaopen_libtinyxmllua”中将需要暴露的接口注册到全局表中,如下:

extern int luaopen_libtinyxmllua(lua_State *L) {
    lua_register(L,"LuaXML_ParseFile",LuaXML_ParseFile);
    return 1;
}

然后实现接口“LuaXML_ParseFile”,这个接口的定义需要保证返回值是int且唯一形参为“lua_State *L”,如下:

extern int LuaXML_ParseFile (lua_State *L) {
    const char* sFileName = luaL_checkstring(L,1);
    XMLDocument doc;
    doc.LoadFile(sFileName);
    LuaXML_Ananysis(L,&doc);
    fclose(fp);
    return 1;
}

进入“LuaXML_ParseFile”之后就是C++的流程,需要给“Lua”的部分,就通过“LuaState”进行结果的传递,如下:

//LuaXML_AnanysisOss执行XML的解析和数据组织工作
extern void LuaXML_Ananysis (lua_State *L,XMLNode* pNode){
    XMLNode *pChild = pNode->FirstChild();
    for(;pChild;pChild = pChild->NextSibling()) {
        if(strcmp(pChild->Value(),"table_list") == 0){
            break;
        }
    }
    //建表,表中存有每个字段类型
    lua_pushstring(L,"table_map");
    lua_newtable(L);
    XMLNode* meta_table = pChild->FirstChild();
    for(;meta_table;meta_table = meta_table->NextSibling()){
        const XMLElement* meta_elem = meta_table->ToElement();
        if(meta_elem){
            const char* meta_name = LuaXML_GetNodeNameAttr(meta_table);
            type_struct_map item_map;
            table_map[node_name] = meta_map;
            lua_pushstring(L,node_name);
            LuaXML_ParseXMLNode(L,meta_table,false);
            lua_settable(L,-3);
        }
    }
    lua_setglobal(L,"table_map"); 
}

编译生成so文件

g++ tinyxml2.cpp tinyxml_lua.cpp -fPIC -O2 -shared  -L ./liblua.a -I /usr/include/lua5_4/ -o libtinyxmllua.so

这里有一点需要注意,就是我们可能机器上安装有多个版本的lua,所以需要通过-L和-I指定链接的.a文件和头文件;若是静态库文件和头文件版本不对,会在运行中遇到段错误




在Lua中使用


准备好so之后,我们就可以在lua中使用了,如下:

require("libtinyxmllua")                                                                           
tb=LuaXML_ParseFile("test.xml")
print(#tb)
for key,val in pairs(table_map) do
    print(key,val)
    for key_1,val_1 in pairs(val) do
        print(key_1,val_1)
    end
end

直接“require”对应的库之后,直接调用即可“LuaXML_ParseFile”


运行效果如下图所示:

meta_table      table: 0x194ee40
meta_entry2     int
meta_entry3     int
meta_entry5     int
meta_entry1     int
meta_entry4     int


标签: LUAso
返回列表

上一篇:第五次引擎编程尝试

没有最新的文章了...

相关文章

Lua热更新机制(下)

Lua热更新机制(下)

Lua热更新机制怎么解决热更的这些问题场景拆分    Lua代码的实体可拆分出三类:配置、逻辑和运行时状态,其中逻辑分为常规的接口和闭包内的逻辑,运行时状态又分为全局变量和闭包内的局部变量,这里结合skynet的解决方案进行描述。热更的核心问题    1)新老版本的差异是什么?   &nb...

Lua的Upvalue和闭包(二)

Lua的Upvalue和闭包(二)

Lua闭包和Upvalue的实现    前面文章介绍了Lua闭包和upvalue的概念,本文简单过一下Lua对于闭包和upvalue的实现以加深理解。Lua闭包结构    Lua在内存的结构如下所示:#define ClosureHeader \ CommonHeader; lu_by...

Lua的Upvalue和闭包(一)

Lua的Upvalue和闭包(一)

upvalue什么是upvalue    Lua的upvalue指的是函数内引用的非全局的外部变量,这么说有两层意思:    1)他是非全局的变量,即这个变量是用local修饰的    2)它是外部变量,即这个变量不是在函数内定义的变量如下代码所示:local test...

Lua的垃圾回收(上)

Lua 5.3版本的垃圾回收垃圾回收算法    垃圾回收算法一般分为两类:引用计数法和标记扫描法。引用计数法    所谓引用计数法,是指在为对象申请内存的时候,在分配的内存块预留一块区域用于存放这块内存被引用的次数,当被引用的时候增一,解引用的时候减一,当这块内存的引用次数降到0的时候,这块内存被认为不可访问,直接被回...

关于LUA(下)

关于LUA(下)

Lua与OOP    Lua是面向过程的语言,不提供面向对象的特性,但是我们可以利用Lua的元表和元方法模拟面向对象的效果。OOP的特性封装    所谓封装,是隐藏对象的属性和细节,仅对外暴露公共的访问方式。本质上分为两层:    1)成员变量和成员方法,提升代码的内聚性,降低模...

Lua和C

Lua和C

一.背景    在实际游戏业务运营过程中,经常会出现一些紧急的配置修改、bug修复等;这种规划外的变更行为希望能做到用户无感知,否则对于游戏体验和产品口碑有很大影响,在此背景下,热更新能力成为成熟上线游戏的标准配置。    一般情况下,后台逻辑热更新能力的技术方案有两种:    ...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。