Skip to content

Instantly share code, notes, and snippets.

@zachallaun
Forked from dcampbell24/gist:3470851
Created August 25, 2012 20:54
Show Gist options
  • Save zachallaun/3470855 to your computer and use it in GitHub Desktop.
Save zachallaun/3470855 to your computer and use it in GitHub Desktop.
julia ccall macro

Macros in Julia

Say you want to use glfw (an openGL wrapper) from Julia...

You could do:

ccall(dlsym(glfw, :glfwInit), Int, ())

That's okay with glfwInit, but what about a more complex call:

ccall(dlsym(glfw, :glCall), ReturnType,
      (Type1, Type2, Type3),
      arg1, arg2, arg3)

But that's not very nice... So you could wrap it in a function:

function glfwInit()
  ccall(dlsym(glfw, :glfwInit), Int, ())
end

glfwInit()

Except you have to define a lot of these functions...

function glCall(arg2::Type1, arg2::Type2, arg3::Type3)
  ccall(dlsym(glfw, :glCall), ReturnType,
        (Type1, Type2, Type3),
        arg1, arg2, arg3)
end

They all look relatively similar... Macro time!

macro ccallWrap(lib, fnSym, retType, argTypes)
    argTypes = eval(argTypes)
    assertOp = :(sym::Type).head
    args = [gensym() for i in 1:length(argTypes)]
    fnArgs = [Expr(assertOp, {args[i], argTypes[i]}, Any)
                 for i in 1:length(argTypes)]

    dlsymExpr = Expr(:call, {:dlsym, lib, fnSym}, Any)
    ccallExpr = Expr(:call,{:ccall, dlsymExpr, retType, argTypes, args...},Any)
    fnBody = Expr(:block, {ccallExpr}, Any)
    fnCall = Expr(:call,{eval(fnSym), fnArgs...}, Any)
    ccallFn = Expr(:function, {fnCall, fnBody}, Any)
    line1 = Expr(:line, {1}, Any)

    fnBlock = Expr(:block, {line1, Expr(:global, {eval(fnSym)}, Any), ccallFn}, Any)
    fnBlock
end 

Now you can just do:

@ccallWrap(glfw, :glCall, ReturnType, (Type1, Type2, Type3))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment