C++与Lua交互实例 -- 矩阵的加减乘除(版本二)

Posted ufgnix0802

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++与Lua交互实例 -- 矩阵的加减乘除(版本二)相关的知识,希望对你有一定的参考价值。

C++与Lua交互实例 – 矩阵的加减乘除(版本二)

TIPS:关于使用矩阵的加减乘除测试C++与Lua的交互以及下面没讲述到的知识点可以阅读第一版:

https://blog.csdn.net/qq135595696/article/details/128960951

同时下面两个方式矩阵的数据都来源于C++端,只是第一种是在C++端进行结果比较展示,第二种方式(userdata)是在lua端进行结果比较展示。

下面C++端引入第三方开源库测试lua端矩阵的运算是否正确,参考链接如下:

http://eigen.tuxfamily.org/index.php?title=3.4

https://blog.csdn.net/qq_41854911/article/details/119814660

https://blog.csdn.net/thlzzz/article/details/110451022

CppToLua1

CppToLua.cpp

#include <iostream>
#include <vector>
#include <assert.h>
#include <Dense>
#include "lua.hpp"
using std::cout;
using std::endl;
using std::cin;

static int gs_Top = 0;
#define STACK_NUM(L) \\
        gs_Top = lua_gettop(L); \\
        std::cout<<"stack top:"<< gs_Top <<std::endl\\

// 矩阵运算
enum class MATRIX_OPERATE 
    ADD,
    SUB,
    MUL,
    DIV,
    NONE
;


#define LUA_SCRIPT_PATH "matrix2.0.lua"
static std::vector<std::vector<double>> gs_mat1;
static std::vector<std::vector<double>> gs_mat2;


static bool OutPrint(const std::vector<std::vector<double>>& data) 
    for (int32_t i = 0; i < data.size(); i++) 
        for (int32_t j = 0; j < data[0].size(); j++)
            std::cout << " "<< data[i][j];
        std::cout << '\\n';
    
    std::cout << "......\\n";
    return true;


static bool Init(lua_State* L) 
    assert(NULL != L);
    gs_mat1.clear();
    gs_mat2.clear();
    
    if (luaL_dofile(L, LUA_SCRIPT_PATH)) 
        printf("%s\\n", lua_tostring(L, -1));
        return false;
    
    return true;


static bool CreateLuaArr(lua_State* L, const std::vector<std::vector<double>>& data) 
    assert(NULL != L);
    //STACK_NUM(L);
    lua_newtable(L);
    for (int32_t i = 0; i < data.size(); i++) 
        lua_newtable(L);
        for (int32_t j = 0; j < data[0].size(); j++) 
            lua_pushnumber(L, data[i][j]);
            lua_rawseti(L, -2, j + 1);
        
        lua_rawseti(L, -2, i + 1);
    
    //STACK_NUM(L);
    return true;


static bool GetLuaArr(lua_State* L, std::vector<std::vector<double>>& outData) 
    assert(NULL != L);
    outData.clear();
    bool result = false;

    int32_t row = 0;
    int32_t col = 0;

    if (LUA_TTABLE != lua_type(L, -1)) 
        goto Exit;
    

    if (LUA_TTABLE != lua_getfield(L, -1, "tbData")) 
        goto Exit;
    

    lua_getfield(L, -2, "nRow");
    row = lua_tointeger(L, -1);
    lua_pop(L, 1);
    lua_getfield(L, -2, "nColumn");
    col = lua_tointeger(L, -1);
    lua_pop(L, 1);

    for (int32_t i = 0; i < row; i++) 
        lua_rawgeti(L, -1, i + 1);
        std::vector<double> data;
        for (int32_t j = 0; j < col; j++) 
            lua_rawgeti(L, -1, j + 1);
            data.push_back(lua_tonumber(L, -1));
            lua_pop(L, 1);
        
        outData.push_back(data);
        lua_pop(L, 1);
    
    
    //维持lua堆栈平衡
    lua_pop(L, 1);
    result = true;
Exit:
    return true;


static bool MatrixOperate(lua_State* L,
    std::vector<std::vector<double>>& outData, MATRIX_OPERATE type) 
    outData.clear();
    const char* funcName = NULL;
    bool        result   = false;
    switch (type) 
    case MATRIX_OPERATE::ADD:
        funcName = "MatrixAdd";
        break;
    case MATRIX_OPERATE::SUB:
        funcName = "MatrixSub";
        break;
    case MATRIX_OPERATE::MUL:
        funcName = "MatrixMul";
        break;
    case MATRIX_OPERATE::DIV:
        funcName = "MatrixDiv";
        break;
    case MATRIX_OPERATE::NONE:
        break;
    default:
        break;
    

    lua_getglobal(L, funcName);
    luaL_checktype(L, -1, LUA_TFUNCTION);

    //添加形参
    CreateLuaArr(L, gs_mat1);
    CreateLuaArr(L, gs_mat2);

    //调用函数
    if (lua_pcall(L, 2, 1, 0)) 
        printf("error[%s]\\n", lua_tostring(L, -1));
        goto Exit;
    

    GetLuaArr(L, outData);
    result = true;
Exit:
    return result;


static bool APIMatrixOperate(const std::vector<std::vector<double>>& data1,
    const std::vector<std::vector<double>>& data2, MATRIX_OPERATE type, Eigen::MatrixXd& outResMat) 
    Eigen::MatrixXd mat1(data1.size(), data1[0].size());
    Eigen::MatrixXd mat2(data2.size(), data2[0].size());

    for (int i = 0; i < data1.size(); i++) 
        for (int j = 0; j < data1[0].size(); j++) 
            mat1(i, j) = data1[i][j];
        
    

    for (int i = 0; i < data2.size(); i++) 
        for (int j = 0; j < data2[0].size(); j++) 
            mat2(i, j) = data2[i][j];
        
    

    switch (type) 
    case MATRIX_OPERATE::ADD:
        outResMat = mat1 + mat2;
        break;
    case MATRIX_OPERATE::SUB:
        outResMat = mat1 - mat2;
        break;
    case MATRIX_OPERATE::MUL:
        outResMat = mat1 * mat2;
        break;
    case MATRIX_OPERATE::DIV:
        outResMat = mat1 * (mat2.inverse());
        break;
    case MATRIX_OPERATE::NONE:
        break;
    default:
        break;
    

    return true;


static bool Run(lua_State* L) 
    assert(NULL != L);

    std::vector<std::vector<double>> addData;
    std::vector<std::vector<double>> subData;
    std::vector<std::vector<double>> mulData;
    std::vector<std::vector<double>> divData;

    Eigen::MatrixXd addApiData;
    Eigen::MatrixXd subApiData;
    Eigen::MatrixXd mulApiData;
    Eigen::MatrixXd divApiData;

    // 运算
    gs_mat1 =   1,2,3 ,  4,5,6  ;
    gs_mat2 =   2,3,4 ,  5,6,7  ;
    MatrixOperate(L, addData, MATRIX_OPERATE::ADD);
    APIMatrixOperate(gs_mat1, gs_mat2, MATRIX_OPERATE::ADD, addApiData);

    gs_mat1 = addData;
    gs_mat2 =  1,1,1,1,1,1 ;
    MatrixOperate(L, subData, MATRIX_OPERATE::SUB);
    APIMatrixOperate(gs_mat1, gs_mat2, MATRIX_OPERATE::SUB, subApiData);

    gs_mat1 =  1,2,3,4,5,6 ;
    gs_mat2 =  7,8,9,10,11,12 ;
    MatrixOperate(L, mulData, MATRIX_OPERATE::MUL);
    APIMatrixOperate(gs_mat1, gs_mat2, MATRIX_OPERATE::MUL, mulApiData);

    gs_mat1 =  41,2,3,424,5,6,742,8,11 ;
    gs_mat2 =  1,2,1,1,1,2,2,1,1 ;
    MatrixOperate(L, divData, MATRIX_OPERATE::DIV);
    APIMatrixOperate(gs_mat1, gs_mat2, MATRIX_OPERATE::DIV, divApiData);

    // 输出
    cout << "================加法:================" << endl;
    OutPrint(addData);
    cout << "正确答案:\\n" << addApiData << endl;
    cout << "================减法:================" << endl;
    OutPrint(subData);
    cout << "正确答案:\\n" << subApiData << endl;
    cout << "================乘法:================" << endl;
    OutPrint(mulData);
    cout << "正确答案:\\n" << mulApiData << endl;
    cout << "================除法:================" << endl;
    OutPrint(divData);
    cout << "正确答案:\\n" << divApiData << endl;
    return true;



static bool UnInit() 
    return true;



int main020811() 
    lua_State* L = luaL_newstate();
    
    luaL_openlibs(L);

    if (Init(L)) 
        Run(L);
    

    UnInit();

    lua_close(L);
	return 0;

matrix2.0.lua

local _class = 

function class(super)
    local tbClassType = 
    tbClassType.Ctor  = false
    tbClassType.super = super
    tbClassType.New   = function(...)
        local tbObj   = 
        do
            local funcCreate
            funcCreate = function(tbClass,...)
                if tbClass.super then
                    funcCreate(tbClass.super,...)
                end
                
                if tbClass.Ctor then
                    tbClass.Ctor(tbObj,...)
                end
            end
            funcCreate(tbClassType,...)
        end
        -- 防止调用Ctor初始化时,在Ctor内部设置了元表的情况发生
        if getmetatable(tbObj) then
            getmetatable(tbObj).__index = _class[tbClassType] 
        else
            setmetatable(tbObj,  __index = _class[tbClassType] )
        end
        return tbObj
    end

    local vtbl          =  
    _class[tbClassType] = vtbl

    setmetatable(tbClassType,  __newindex = 
        function(tb,k,v)
            vtbl[k] = v
        end
    )

    if super then
        setmetatable(vtbl,  __index = 
            function(tb,k)
                local varRet = _class[super][k]
                vtbl[k]      = varRet
                return varRet
            end
        )
    end
    return tbClassType
end





Matrix = class()

function Matrix:Ctor(data)
    self.tbData = data
    self.nRow   = #data
    if self.nRow > 0 then
        self.nColumn = (#data[1])
    else
        self.nColumn = 0
    end
    -- print("row:",self.nRow," col:",self.nColumn)

    setmetatable(self,
        __add = function(tbSource, tbDest)
            assert(tbSource,"tbSource not e

以上是关于C++与Lua交互实例 -- 矩阵的加减乘除(版本二)的主要内容,如果未能解决你的问题,请参考以下文章

游戏开发实现C++与Lua交互!

lua 与 c++或者c 交互的底层原理谁能解释一下?最最底层的,为啥它们调用C或者C++的函数?

Lua和C++交互详细总结

lua与c的交互(运用)

LuaJavaBridge - lua与java互操作的简单解决方案

C与lua交互--lua调用栈分析