lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




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;
}