Lua和so

ronald1年前职场8130

    实际在应用开发过程中,会用到很多第三方的库;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
返回列表

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

没有最新的文章了...

相关文章

K8S入门-原理篇

K8S入门-原理篇

一. K8S总体架构及组件功能    K8S总体架构图如下所示:    在K8S中,整个集群划分为控制节点和工作节点,其中控制节点分为:    ·ETCD        一个分布式的数据库,用于存储集...

Lua的垃圾回收(下)

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

关于LUA(下)

关于LUA(下)

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

LUA数据结构(一)

LUA数据结构(一)

Lua数据结构    Lua有8个基本类型,分别为:nil、boolean、number、string、userdata、function、thread和table;我们可以通过函数type函数获取变量类型,如下:a="cccd" dict={} print(type(a)) print(type(dict)) print(typ...

第五次引擎编程尝试

第五次引擎编程尝试

在前面的章节中,我们已经尝试了制作特效、为游戏添加AI并设置AI的UI,到现在这一步我们希望游戏可以多人联网,我们一步步来。开启多人游戏通过这个我们可以看到角色移动在CS之间同步,但是真正运行的时候发现,距离真正的多人联网游戏还很遥远:1)射击的时候CS端的弹道不同步2)NPC的状态CS端不同步3)游戏状态CS端不同步... ...针对上述问题,我们逐步来看:让发射物在CS之间同步原先的实现流程如...

Lua的Upvalue和闭包(一)

Lua的Upvalue和闭包(一)

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

发表评论    

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