lua手动添加Opencv Mat对象

错误写法

在lua的userdata中分配内存

使用c++的placement new 调用 Mat 类的构造函数,把对象分配在lua的userdata空间中

Mat的生命周期由lua虚拟机管理,跟随lua变量生命周期

void createMat(const std::string& filename,Mat *result) {
	Mat img = cv::imread(filename, cv::IMREAD_COLOR);
	Mat* mat2 = new(result) Mat();
	*mat2 = img;
}
//在lua中申请内存
Mat* luaImage = static_cast<Mat*>(lua_newuserdata(L, sizeof(Mat)));
createMat(filename, luaImage);

这个写法不能调用Mat的析构函数会导致内存泄漏

正确写法

把Mat的析构函数注入到lua表里,名字为__gc

// my_module.cpp
#include <lua.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;

// GC函数
static int mat_gc(lua_State* L) {
    Mat** pmat = static_cast<Mat**>(luaL_checkudata(L, 1, "MatMetaTable"));
    if (*pmat) {
        delete *pmat;
        *pmat = nullptr;
    }
    return 0;
}

// 创建Mat对象
static int mat_create(lua_State* L) {
    const char* filename = luaL_checkstring(L, 1);
    
    // 创建userdata存储Mat指针
    Mat** ud = static_cast<Mat**>(lua_newuserdata(L, sizeof(Mat*)));
    *ud = new Mat(imread(filename, IMREAD_COLOR));
    
    // 设置元表
    luaL_getmetatable(L, "MatMetaTable");
    lua_setmetatable(L, -2);
    
    return 1;
}

// Mat克隆方法
static int mat_clone(lua_State* L) {
    Mat** src = static_cast<Mat**>(luaL_checkudata(L, 1, "MatMetaTable"));
    
    // 创建新userdata
    Mat** dst = static_cast<Mat**>(lua_newuserdata(L, sizeof(Mat*)));
    *dst = new Mat((**src).clone());
    
    // 设置元表
    luaL_getmetatable(L, "MatMetaTable");
    lua_setmetatable(L, -2);
    
    return 1;
}

// 保存Mat到文件
static int mat_save(lua_State* L) {
    Mat** pmat = static_cast<Mat**>(luaL_checkudata(L, 1, "MatMetaTable"));
    const char* filename = luaL_checkstring(L, 2);
    
    bool success = imwrite(filename, **pmat);
    lua_pushboolean(L, success);
    return 1;
}

// 注册模块
static const luaL_Reg mat_methods[] = {
    {"create", mat_create},
    {"save", mat_save},
    {NULL, NULL}
};

static const luaL_Reg mat_metamethods[] = {
    {"__gc", mat_gc},
    {"clone", mat_clone},
    {NULL, NULL}
};

extern "C" int luaopen_my_module(lua_State* L) {
    // 创建元表
    luaL_newmetatable(L, "MatMetaTable");
    
    // 设置元方法
    luaL_setfuncs(L, mat_metamethods, 0);
    
    // 设置__index指向自身以访问方法
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    
    // 注册模块函数
    luaL_newlib(L, mat_methods);
    return 1;
}

lua脚本示例

-- script.lua
local mymod = require "my_module"

-- 创建Mat对象
local mat1 = mymod.create("input.jpg")

-- 克隆Mat对象
local mat2 = mat1:clone()

-- 转换为灰度图(示例处理)
-- 注意:实际需要实现cvtColor绑定,此处仅为演示
-- function mat1:cvtColor()
--     mymod.cvtColor(self, ...)
-- end

-- 保存处理结果
mat2:save("output_clone.jpg")

-- 显式释放资源(非必要,Lua GC会自动管理)
mat1 = nil
mat2 = nil
collectgarbage()

注册其他函数

// 灰度转换
static int mat_cvtColor(lua_State* L) {
    Mat** pmat = static_cast<Mat**>(luaL_checkudata(L, 1, "MatMetaTable"));
    int code = luaL_checkinteger(L, 2);
    
    Mat* result = new Mat();
    cvtColor(**pmat, *result, code);
    
    Mat** dst = static_cast<Mat**>(lua_newuserdata(L, sizeof(Mat*)));
    *dst = result;
    
    luaL_getmetatable(L, "MatMetaTable");
    lua_setmetatable(L, -2);
    
    return 1;
}

注册到字典中

static const luaL_Reg mat_metamethods[] = {
    {"__gc", mat_gc},
    {"clone", mat_clone},
    {"cvtColor", mat_cvtColor},
    {NULL, NULL}
};

使用示例

local gray = mat1:cvtColor(COLOR_BGR2GRAY)
gray:save("gray.jpg")
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值