错误写法
在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
#include <opencv2/opencv.hpp>
#include <lua.hpp>
using namespace cv;
// GC function to be called by Lua
static int auto_gc(lua_State* L) {
Mat* mat = *static_cast<Mat**>(lua_touserdata(L, 1));
delete mat;
return 0;
}
void createMat(const std::string& filename, Mat** result) {
Mat* img = new Mat(cv::imread(filename, cv::IMREAD_COLOR));
*result = img;
}
extern "C" int createMat_lua(lua_State* L) {
const char* filename = luaL_checkstring(L, 1);
// 创建一个新的table
lua_newtable(L);
// 创建userdata保存Mat*指针
Mat** luaImage = static_cast<Mat**>(lua_newuserdata(L, sizeof(Mat*)));
createMat(filename, luaImage);
// 将userdata放入table中
lua_setfield(L, -2, "mat");
// 创建元表
if (luaL_newmetatable(L, "MatMetaTable")) {
lua_pushcfunction(L, auto_gc);
lua_setfield(L, -2, "__gc");
}
// 将元表设置为table的元表
lua_setmetatable(L, -2);
return 1; // 返回table
}
extern "C" int luaopen_my_module(lua_State* L) {
lua_register(L, "createMat", createMat_lua);
return 1;
}
int main() {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaopen_my_module(L);
// Run Lua script
luaL_dofile(L, "script.lua");
lua_close(L);
return 0;
}