Lua和so

ronald9个月前职场6380

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

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

没有最新的文章了...

相关文章

    栈(stack)一种操作受限的线性结构,限定仅能在尾部进行插入和删除,能进行插入和删除操作的一端叫做栈顶,而另一端叫做栈底;我们将插入栈的操作叫做入栈,从栈中删除元素的操作叫做出栈,栈是一个先入后出(FILO)的数据结构,即先入栈的元素会后出栈。    栈最常被我们接触的场景就是函数调用了,在进程地址空间中,有...

聊一聊面试(一)

聊一聊面试(一)

  前些天一些叔伯辈的小孩大学要毕业了,可能感觉计算机行业赚的有点多,一些不怕加班的也想进入这个行业,于是就辗转找到我,希望帮忙做一些这个方面的面试辅导;而我趁着这个机会,对过去的一些思考进行沉淀,分享出来和大家交流一下。    在我看来,面试主要考察能力项包括:专业能力、沟通能力、思维能力、学习能力、思考能力和抗压能力五大方面;投射到实...

K8S入门-概念篇(下)

K8S入门-概念篇(下)

一. volume    volume解决的是pod上不同容器之间共享文件的问题和容器文件持久化的问题;K8S提供了以下几类volume:1. hostPath    hostPath是一种通过pod所在node上的文件系统指定的文件或者目录实现文件共享,如下所示,先在Pod内定义一个volume,类型定义为hostP...

几种Lua和C交叉编程的程序写法

Lua程序调用C接口//另一个待Lua调用的C注册函数。 static int sub2(lua_State* L) {     double op1 = luaL_checknumber(L,1);     double op2 ...

协程-有栈协程(coroutine)

协程-有栈协程(coroutine)

概述    后台架构的微服务化,原先的单体应用被按照功能模块切分为若干进程组承担,此种架构演化带来的收益诸如:单进程复杂度降低,代码维护成本降低发布影响范围缩小,发布灵活性提升计算资源更精准的分配... ...    但是这种架构带来的另外的变化就是,原先由单进程承载的事务,可能涉及几个甚至十几个进程;在这种情况下,采...

协程-无栈协程(下)

无栈协程库——protothread    ProtoThread源码如下所示:#define LC_INIT(s) s = 0; #define LC_RESUME(s) switch(s) { case 0: #define LC_SET(s)...

发表评论    

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