错误写法
在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")