Lua和so

ronald2个月前职场1640

    实际在应用开发过程中,会用到很多第三方的库;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环境搭建

LUA环境搭建

    本文针对Lua新手,介绍Lua开发环境的搭建。环境搭建目标语法高亮,自动补齐语法错误检查方法跳转lua脚本本地运行断点设置及调试功能编辑器选择    主流代码编辑器有vscode、rider、clion。其中下载链接:    Documentation for Visua...

Lua和C

Lua和C

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

Lua的垃圾回收(下)

Lua 5.3版本的垃圾回收Lua垃圾回收源码实现    结合前面描述的垃圾回收的流程,我们参照源码进行逐个的拆解和介绍。    lua的垃圾回收主要都是在接口luaC_step里面完成的,这里面本质上是控制了一个状态机,根据global_State->gcstate进行渐进式的垃圾回收处理。GCSpause&n...

Lua的Upvalue和闭包(二)

Lua的Upvalue和闭包(二)

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

LUA数据结构(三)

Lua数据结构userdata    Lua官方的介绍:userdata是一种用户自定义数据,用于表示一种由应用程序或者C/C++语言库创建的类型,可以将任意C/C++类型的数据(通常是struct、指针)存储到Lua变量中调用。    在实际应用过程中,C/C++接口调用LuaL_newuserdata就会分配指定大...

发表评论    

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