Skip to content

Instantly share code, notes, and snippets.

@vrld
Created November 27, 2012 13:16
Show Gist options
  • Save vrld/4154182 to your computer and use it in GitHub Desktop.
Save vrld/4154182 to your computer and use it in GitHub Desktop.
Helpers for exposing (parts of) C++ structs to Lua, e.g. to be passed around in "glue code"
#include <lua_proxy.hpp>
#include <opencv.hpp>
// Exposing cv::Mat to Lua
template<> struct LuaXTraits<cv::Mat>
{
constexpr static const char *name()
{
return "Type.cv::Mat";
}
};
int l_imread(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
cv::Mat img = cv::imread(path);
if (NULL != img.data)
{
LuaProxy<cv::Mat>::push_new_with_mtable(L, new cv::Mat(img));
return 1;
}
// else (see https://gist.github.com/4154228 for a shorter version of the following)
lua_pushnil(L);
luaL_Buffer b;
luaL_buffinit(L, &b);
luaL_addstring(&b, "Cannot read image from `");
luaL_addstring(&b, path);
luaL_addstring(&b, "'.");
luaL_pushresult(&b);
return 2;
}
int l_imwrite(lua_State *L)
{
cv::Mat *img = LuaProxy<cv::Mat>::get(L, 1);
const char *path = luaL_checkstring(L, 2);
if (cv::imwrite(path, *img))
{
lua_pushboolean(L, true);
return 1;
}
// else
lua_pushnil(L);
luaL_Buffer b;
luaL_buffinit(L, &b);
luaL_addstring(&b, "Cannot write image to `");
luaL_addstring(&b, path);
luaL_addstring(&b, "'.");
luaL_pushresult(&b);
return 2;
}
#pragma once
#include <stdexcept>
#include <lua.hpp>
template<typename T>
struct LuaXTraits
{
constexpr static const char *name()
{
throw std::runtime_error("LuaXTraits<T> not implemented for this type!");
return "Type.NeedsImplementation"; // never reached
}
};
template<typename T>
struct LuaProxy
{
T *ptr;
static T *push_new(lua_State *L, T *ptr)
{
LuaProxy<T> *p = (LuaProxy<T> *)lua_newuserdata(L, sizeof(LuaProxy<T>));
if (NULL == p)
luaL_error(L, "Cannot create new userdata!");
p->ptr = ptr;
return ptr;
}
static int __gc(lua_State *L)
{
LuaProxy *p = (LuaProxy<T> *)lua_touserdata(L, 1);
if (NULL != p && NULL != p->ptr)
delete p->ptr;
return 0;
}
static inline T *get(lua_State *L, int i)
{
LuaProxy<T> *p = (LuaProxy<T> *)luaL_checkudata(L, i, LuaXTraits<T>::name());
return p->ptr;
}
static int newmetatable(lua_State *L)
{
int rc = luaL_newmetatable(L, LuaXTraits<T>::name());
if (rc)
{
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, LuaProxy<T>::__gc);
lua_setfield(L, -2, "__gc");
}
return rc;
}
static T *push_new_with_mtable(lua_State *L, T *ptr)
{
push_new(L, ptr);
newmetatable(L);
lua_setmetatable(L, -2);
return ptr;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment