On 2/8/06, Adam D. Moss <adam@gimp.org> wrote:
Issac Trotts wrote:
> A Google search for "userdata expected, got userdata" came up empty, so
> I'm hoping someone here knows what's going on.
There are two types of userdata: light and heavy. I guess
you're supplying one and the API expects the other. Sadly,
it seems impossible to distinguish between the two types on
the Lua side.
Thanks for your reply. I worked around the issue by writing a
higher-level C function that does some extra work so the caller doesn't
have to allocate a buffer. From what you're saying, this is
probably a good thing. The code is attached below.
Issac
/* do_gl_selection(selection_buffer_size, proc)
*
* proc is a procedure that calls glInitNames(), glPushName(), and glLoadName(), as in the
* OpenGL demo select.c, picksquare.c and pickdepth.c.
*
* The returned value is an array of hit records.
*/
int do_gl_selection(lua_State* L)
{
int bufsize, num_hits;
GLuint* select_buf;
bufsize = luaL_checkint(L,1);
select_buf = calloc(bufsize,sizeof(GLuint));
glSelectBuffer(bufsize, select_buf);
(void)glRenderMode(GL_SELECT);
/* Call the procedure that was passed in. */
{
luaL_checktype(L,2,LUA_TFUNCTION);
if(lua_pcall(L,0,0,0) != 0) {
fprintf(stderr,"Unable to run callback procedure in do_gl_selection:
%s\n",
lua_tostring(L,-1));
}
}
/* Change the render mode back to the default and get the number of
* selection hits. */
num_hits = glRenderMode(GL_RENDER);
lua_newtable(L); /* ret */
/* Process the hits. */
{
GLint i;
GLuint j, num_names, *ptr;
ptr = (GLuint *) select_buf;
for (i = 0; i < num_hits; i++) { /* for each hit */
/*
Push a hit record (table) onto the list of things to return. */
/*
We'll call this table `hitrecord', even though it is anonymous in
* Lua. */
lua_newtable(L);
num_names = *ptr;
/* hitrecord.num_names = *ptr */
{
lua_pushstring(L, "num_names");
lua_pushnumber(L, *ptr);
lua_settable(L,-3);
ptr++;
}
/* hitrecord.z1 = *ptr / (2**32-1) */
{
lua_pushstring(L, "z1");
lua_pushnumber(L, *ptr/(pow(2.0,32.0)-1.0));
lua_settable(L,-3);
ptr++;
}
/* hitrecord.z2 = *ptr / (2**32-1) */
{
lua_pushstring(L, "z2");
lua_pushnumber(L, *ptr/(pow(2.0,32.0)-1.0));
lua_settable(L,-3);
ptr++;
}
for
(j = 0; j < num_names; j++) { /* for each name */
/* hitrecord[j+1] = *ptr */
lua_pushnumber(L, j+1);
lua_pushnumber(L, *ptr);
lua_settable(L,-3);
ptr++;
}
/* Append hitrecord to the ret table. */
{
lua_pushnumber(L, i+1);
lua_pushvalue(L,-2); /* hitrecord */
lua_settable(L,2); /* ret */
}
/* Remove hitrecord from the stack. */
assert(lua_istable(L,-1));
assert(lua_istable(L,-2));
lua_pop(L,1);
assert(lua_istable(L,-1));
assert(lua_isnumber(L,-2));
assert(lua_gettop(L)==2);
}
}
free(select_buf);
return 1;
}