• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

三国杀(3):原始C/C++ lua 编译 集成,及使用介绍

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

一. c++ 调用lua

 

1. lua文件

str = "I am learning lua!"
tbl = {name = "shun", id = 20200501}
function add(a,b)
    return a + b
end

//////////////////////////////////////////////////////////////////////////////////////////

2. main.cpp文件

 

#include <iostream>
#include <string.h>
using namespace std;

extern "C"
{
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
}

 

int main()
{
    //1.创建Lua状态
    lua_State *L = luaL_newstate();
    if (L == NULL)
    {
        return -1;
    }

    //2.加载lua文件
    int bRet = luaL_loadfile(L,"scripts/testlua.lua");
    if(bRet)
    {
        cout<<"load file error"<<endl;
        return -1;
    }

    //3.运行lua文件
    bRet = lua_pcall(L,0,0,0);
    if(bRet)
    {
        cout<<"pcall error"<<endl;
        return -1;
    }

    //4.读取变量
    lua_getglobal(L,"str");
    string str = lua_tostring(L,-1);
    cout<<"str = "<<str.c_str()<<endl;        //str = I am so cool~

    //5.读取table
    lua_getglobal(L,"tbl");
    lua_getfield(L,-1,"name");
    str = lua_tostring(L,-1);
    cout<<"tbl:name = "<<str.c_str()<<endl; //tbl:name = shun

    //6.读取函数
    lua_getglobal(L, "add");        // 获取函数,压入栈中
    lua_pushnumber(L, 10);            // 压入第一个参数
    lua_pushnumber(L, 20);            // 压入第二个参数
    int iRet= lua_pcall(L, 2, 1, 0);// 调用函数,调用完成以后,会将返回值压入栈中,2表示参数个数,1表示返回结果个数。
    if (iRet)                        // 调用出错
    {
        const char *pErrorMsg = lua_tostring(L, -1);
        cout << pErrorMsg << endl;
        lua_close(L);
        return -1;
    }
    if (lua_isnumber(L, -1))        //取值输出
    {
        double fValue = lua_tonumber(L, -1);
        cout << "Result is " << fValue << endl;
    }

    //至此,栈中的情况是:
    //=================== 栈顶 ===================
    //  索引  类型      值
    //   4   int:      30
    //   3   string:   shun
    //     2     table:        tbl
    //   1   string:    I am so cool~
    //=================== 栈底 ===================

    //7.关闭state
    lua_close(L);

    return 0;

}

运行结果:

二.lua调用c++


主要两个方法实现:

 

方法一:静态注册

大概顺序就是:在c++中写一个模块函数,将函数注册到lua解释器中,然后由c++去执行我们的lua文件,然后在lua中调用刚刚注册的函数。


1. 在目录下新建一个testlua.lua如下:

    avg, sum = average(10, 20, 30, 40, 50)
    print("The average is ", avg)
    print("The sum is ", sum)


2.新建main.cpp如下:

#include <iostream>
#include <string.h>
using namespace std;

extern "C"
{
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
}


/* 指向Lua解释器的指针 */
lua_State* L;
static int average(lua_State *L)
{
    /* 得到参数个数 */
    int n = lua_gettop(L);
    double sum = 0;
    int i;

    /* 循环求参数之和 */
    for (i = 1; i <= n; i++)
    {
        /* 求和 */
        sum += lua_tonumber(L, i);
    }
    /* 压入平均值 */
    lua_pushnumber(L, sum / n);
    /* 压入和 */
    lua_pushnumber(L, sum);
    /* 返回返回值的个数 */
    return 2;
}

int main ( int argc, char *argv[] )
{

    //1.创建Lua状态
    lua_State *L = luaL_newstate();
    if (L == NULL)
    {
        return -1;
    }

    /* 载入Lua基本库 */
    luaL_openlibs(L);
    /* 注册函数 */
    lua_register(L, "average", average);
    /* 运行脚本 */
    bool bRet = luaL_dofile(L, "scripts/testlua.lua");
    if(bRet)
    {
        cout<<"load file error"<<endl;
        return -1;
    }
    /* 清除Lua */
    lua_close(L);

    /* 暂停 */
    system("pause");
    return 0;
}

执行一下,得到结果:

 


方法2:绑定C++对象

1. 建立工程

2. 封装C++类

1)CMath.H

#ifndef CMATH_H
#define CMATH_H

extern "C"
{
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
}

class CMath
{
public:
    CMath();
    virtual ~CMath(){}
    void setNum(int x);
    int getNum();
    int Add(int x, int y);

    int Sub(int x, int y);
    int Mul(int x, int y);
    private:
        int num;

};

#ifdef __cplusplus
extern "C" {
#endif
    int luaopen_cmath(lua_State *L);
#ifdef __cplusplus
}
#endif
#endif // CMATH_H

 

2) CMath.CPP

#include "cmath.h"
#include "iostream"
using namespace std;


CMath::CMath()
{

}


void CMath::setNum(int x)
{
    num = x;
}
int CMath::getNum()
{
    return 0;
}
int CMath::Add(int x, int y)
{

    cout<<"%p Add="<<this<<",X="<<x<<",Y="<<y<<endl;
    return x + y;
};
int CMath::Sub(int x, int y)
{
    return x-y;
}
int CMath::Mul(int x, int y)
{
    return x*y;
}


////////////////////////////////////////////////////////////////////////////

static int CreateCMath(lua_State* L)
{
    // 创建一个元表为CTest的Table——Lua对象
    *(CMath**)lua_newuserdata(L, sizeof(CMath*)) = new CMath();
    luaL_getmetatable(L, "CMath");
    lua_setmetatable(L, -2);
    return 1;
}

static int DestoryCTest(lua_State* L)
{
    // 释放对象
    delete *(CMath**)lua_topointer(L, 1);
    return 0;
}

static int CallAdd(lua_State* L)
{
    int  cnt = lua_gettop (L);

    // 调用C++类方法的跳板函数。
    CMath* pT = *(CMath**)lua_topointer(L, 1);
    lua_pushnumber(L, pT->Add(lua_tonumber(L, 2), lua_tonumber(L, 3)));
    return 1;
}
static int CallSub(lua_State* L)
{
    int  cnt = lua_gettop (L);

    // 调用C++类方法的跳板函数。
    CMath* pT = *(CMath**)lua_topointer(L, 1);
    lua_pushnumber(L, pT->Sub(lua_tonumber(L, 2), lua_tonumber(L, 3)));
    return 1;
}
static int CallMul(lua_State* L)
{
    int  cnt = lua_gettop (L);

    // 调用C++类方法的跳板函数。
    CMath* pT = *(CMath**)lua_topointer(L, 1);
    lua_pushnumber(L, pT->Mul(lua_tonumber(L, 2), lua_tonumber(L, 3)));
    return 1;
}
static int CallgetNum(lua_State* L)
{
    int  cnt = lua_gettop (L);
    // 调用C++类方法的跳板函数。
    CMath* pT = *(CMath**)lua_topointer(L, 1);
    lua_pushnumber(L, pT->getNum());
    return 1;
}
static int CallsetNum(lua_State* L)
{
    int  cnt = lua_gettop (L);

    // 调用C++类方法的跳板函数。
    CMath* pT = *(CMath**)lua_topointer(L, 1);
    pT->setNum(lua_tonumber(L, 2));
    return 0;
}

static luaL_Reg arraylib_m [] = {
    {"Add", CallAdd},
    {"Sub", CallSub},
    {"Mul", CallMul},
    {"setNum", CallsetNum},
    {"getNum", CallgetNum}, //print(a)时Lua会调用该元方法。
    {NULL, NULL}
};

int luaopen_cmath(lua_State *L){
    // 往lua中注册类
    lua_pushcfunction(L, CreateCMath);    // 注册用于创建类的全局函数
    lua_setglobal(L,  "CMath");

    luaL_newmetatable(L, "CMath");           // 创建一个元表
    lua_pushvalue(L,-1);

    lua_pushstring(L, "__gc");                    // 垃圾回收
    lua_pushcfunction(L, DestoryCTest);
    lua_settable(L, -3);                               // 公共函数调用的实现就在此啊

    lua_pushstring(L, "__index");
    lua_pushvalue(L, -2);                           // 注意这一句,其实是将__index设置成元表自己
    lua_settable(L, -3);

//    lua_pushstring(L, "Add");                     // 放元表中增加一个函数。这样所有基于该元表的Table就都有Add方法了
//    lua_pushcfunction(L, CallAdd);
//    lua_settable(L, -3);
//
//    lua_pushstring(L, "Sub");                     // 放元表中增加一个函数。这样所有基于该元表的Table就都有Add方法了
//    lua_pushcfunction(L, CallSub);
//    lua_settable(L, -3);
//
//    lua_pushstring(L, "Mul");                     // 放元表中增加一个函数。这样所有基于该元表的Table就都有Add方法了
//    lua_pushcfunction(L, CallMul);
//    lua_settable(L, -3);
//
//    lua_pushstring(L, "setNum");                     // 放元表中增加一个函数。这样所有基于该元表的Table就都有Add方法了
//    lua_pushcfunction(L, CallsetNum);
//    lua_settable(L, -3);
//
//    lua_pushstring(L, "getNum");                     // 放元表中增加一个函数。这样所有基于该元表的Table就都有Add方法了
//    lua_pushcfunction(L, CallgetNum);
//    lua_settable(L, -3);
//    lua_register(L, "getNum", CallgetNum);

//    lua_pop(L,1);
    luaL_setfuncs(L,arraylib_m,0);
    return 0;
}


3) main.cpp测试函数

#include <iostream>
#include <string.h>
#include <cmath.h>

using namespace std;


int main (  )
{

    lua_State *L = luaL_newstate();
    if (L == nullptr)
    {
        return -1;
    }

    luaL_openlibs(L);

    luaopen_cmath(L); //打开封装的C++lib库

    int bRet = luaL_dofile(L, "scripts/testlua.lua");
    if (bRet)
    {
        cout << "call testlua.lua file failed" << endl;
        return -1;
    }


    lua_close(L);
    // waiting for console
    cin.get();
    return 0;
}

4) testlua.lua调用C++方法

--第四步:在lua中调用 cpp_add,cpp_sub直接操作
--testlua. lua代码
c = CMath()
d = CMath()
print("c.Add(1, 2) ==> " .. c:Add(1, 2));
print("d.Sub(104, 5) ==> " .. d:Sub(104, 5));
print("d.Mul(104, 5) ==> " .. d:Mul(104, 5));
--c::setNum(23);
print(c:getNum());

--print("d.Add(4, 5) ==> " .. d:Add(4, 5));

5)运行结果

三.总结

lua和c++是通过一个虚拟栈来交互的。

c++调用lua实际上是:由c++先把数据放入栈中,由lua去栈中取数据,然后返回数据对应的值到栈顶,再由栈顶返回c++。

lua调c++也一样:先编写自己的c模块,然后注册函数到lua解释器中,然后由lua去调用这个模块的函数。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Lua.LearningLua.7-userdata发布时间:2022-07-22
下一篇:
lua相关库安装常见问题发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap