我使用带有luaglut的Lua来做一些OpenGL的工作。 luaglut API与gl / glut C API几乎相同。有时,gl函数需要一个指向某些数据的指针,例如:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, oh_crap_a_pointer)
在这种情况下,luaglut绑定会获取包含指针的轻量用户数据。在luaglut演示中,一个名为memarray的小型示例库完成了建立C数组并以轻型用户数据返回指向它的指针的工作。
您可以使用“ memarray”之类的东西:
require 'memarray'
function loadTexture(filename)
local file = assert(io.open(filename, 'rb'))
local data = file:read('*a')
file:close()
local array = memarray('uchar', #data)
array:from_str(data)
return array
end
-- ... later
local texture = loadTexture('whatever.rgba')
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA,
GL_UNSIGNED_BYTE, texture:ptr())
这让我开始思考,为什么我们完全需要内存数组? Lua字符串应该是二进制安全的;我们真正需要的只是获得一个指向
file:read('*a')
返回的字符串的指针,作为轻量级的userdata。看起来像这样: function loadTexture(filename)
local file = assert(io.open(filename, 'rb'))
local data = file:read('*a')
file:close()
return data
end
-- ... later
local stringpointer = require 'stringpointer'
local texture = loadTexture('whatever.rgba')
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA,
GL_UNSIGNED_BYTE, stringpointer.get(texture))
当然我们传递字符串而不是指针,因为如果没有更多引用,GC可以释放字符串所在的内存,从而使指针无效。在内部,Lua字符串是不可变的,并且无论如何都可以通过引用传递,因此这没什么大不了的。
代码
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int get_pointer(lua_State *L)
{
luaL_checktype(L, 1, LUA_TSTRING);
lua_pushlightuserdata(L, (void *)lua_tostring(L, 1));
return 1;
}
int luaopen_stringpointer(lua_State *L)
{
const luaL_Reg api[] = {
{"get", get_pointer},
{NULL, NULL}
};
#if LUA_VERSION_NUM == 501
luaL_register(L, "stringpointer", api);
#else
luaL_newlib(L, api);
#endif
return 1;
}
它很小,但是我的C生锈了,所以也许我做了一些愚蠢的事情。到目前为止,它似乎工作正常。欢迎任何输入。
#1 楼
我不是Lua专家,但我至少可以为您提供有关您的C代码的指针(无双关语)。您的
get_pointer
函数看起来不错,但可以做得更多简洁! Lua提供了结合了luaL_checkstring
和luaL_checktype
的luaL_tostring
函数。因此,您可以这样做:int get_pointer(lua_State *L)
{
lua_pushlightuserdata(L, (void *) luaL_checkstring(L, 1));
return 1;
}
评论
为什么有int get_pointer(lua_State * L)和int luaopen_stringpointer(lua_State * L)不是void函数的原因?我无法从上下文判断它们是否必须返回int。@bazola get_pointer返回的int是从Lua调用它时给出的返回值的数量。这意味着返回堆栈上的最后一件事,将lightuserdata压入之前的行。
luaopen_stringpointer是Lua在需要“ stringpointer”时寻找的功能。返回值在那里具有相同的含义,它返回一个值,一个包含“ get”函数的表。
glTexImage2D对传递给它的字符串数据有什么作用?它拥有它吗?它释放它吗?它会立即使用吗?它会在某个未指定的较晚日期使用它吗?
@EtanReisner它复制数据并在以后使用该副本。它不会尝试在传入的指针处释放内存。它并不是真正的字符串数据,它采用其余参数描述的某种任意格式。