Looking to improve dynamic module execution

  • From: William Adams <william_a_adams@xxxxxxx>
  • To: "luajit@xxxxxxxxxxxxx" <luajit@xxxxxxxxxxxxx>
  • Date: Sun, 5 May 2013 14:28:47 +0000

I have some code that looks like this:

function GetFunctionProtoName(fname)
        local upname = fname:upper();
        local protoname = string.format("PFN%sPROC", upname);

        return protoname;
end

function CastFunctionPointer(fname, funcptr)
        local protoname = GetFunctionProtoName(fname);
        local castfunc = ffi.cast(protoname, funcptr);

        return castfunc;
end

function GetWglFunction(fname)
        local funcptr = gl.wglGetProcAddress(fname);

        if funcptr == nil then
                return nil
        end

        local castfunc = CastFunctionPointer(fname, funcptr);

        return castfunc;
end

Along with this, I have some cdefs that look like this:

ffi.cdef[[
typedef void (* PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, 
GLboolean transpose, const GLfloat *value);
typedef void (* PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, 
GLboolean transpose, const GLfloat *value);
typedef void (* PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, 
GLboolean transpose, const GLfloat *value);
]]

I have another wrapper object, which basically allows me to do:

gl.glUniformMatrix2x3fv(loc, count, transpose, values);

Question:  Is this the best that I can do?  Since I MUST use 
'wglGetProcAddress' to get the address of the function from the library, I can 
NOT simply do 'lib.glUniformMatrix2x3fv'.  I MUST look it up, and then cast it 
to the appropriate type?

I'd like to make this faster/better.  I do in fact save the lookup after it is 
done once, but it still ends up being a lookup in a table every time I want to 
execute the function, which is not as optimal as the case of doing the ffi 
execution directly.

In addition, I'd like to reduce the amount of typing involved in creating these 
function signatures in the first place.  I have considered using reflect.lua, 
and writing the signatures in their normal C function prototype form, then 
using reflect to create the function pointer versions, but I'm just wondering 
if there is a better way.

For the cast problem, Ideally I'd do:
ffi.cdef[[
void glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, 
const GLfloat *value);
]]

local exec(funcname, ...)
  local ffifunctype = ffi.C[funcname];
  return ffi.cast(ffifunctype, wglGetProcAddress(funcname))(...);
end

That would at least allow me to write only the single function prototype, but I 
think this does not quite work right.

Hard question:  Is there a better way?  I have used OpenGL in this case, 
because it forces you to do the wglGetProcAddress (for extension functions), 
but I'd like to use the technique in general with libraries.  Really what I'm 
after is generating the signatures on the fly (running against a debug library 
first), and then getting fast execution like the native ffi calls provide.

-- William
===============================
- Shaping clay is easier than digging it out of the ground.                     
                  

Other related posts: