Passing function pointer to Cxx


#1

I am using the Cxx.jl to wrap a C++ library. Now the C++ library has some methods that take function pointers as arguments. Is there a recommended way to wrap such a function? As a minimal example say I want to wrap

using Cxx
cxx"""
void evaluate(void (*f)() ){
    f();
}
"""

I could pass a julia function by doing

function evaluate(f_jl)
    cxx"void f_xx(){$f_jl();}"
    icxx"evaluate(&f_xx);"
end
f() = println("heyho")
evaluate(f)
heyho

However this does not allow to pass another function later on:

g() = println("heyho")
evaluate(g)

LoadError: Clang did not create a global variable for the given VarDecl
while loading In[3], in expression starting on line 3

 in SetDeclInitializer(::Cxx.ClangCompiler, ::Cxx.CppPtr{Cxx.CxxQualType{Cxx.CppBaseType{Symbol("clang::VarDecl")},(false,false,false)},(false,false,false)}, ::Cxx.CppPtr{Cxx.CxxQualType{Cxx.CppBaseType{Symbol("llvm::Constant")},(false,false,false)},(false,false,false)}) at /home/admin/.julia/v0.5/Cxx/src/cxxstr.jl:35
 in ArgCleanup(::Cxx.ClangCompiler, ::Function, ::Cxx.CppPtr{Cxx.CxxQualType{Cxx.CppBaseType{Symbol("clang::VarDecl")},(false,false,false)},(false,false,false)}) at /home/admin/.julia/v0.5/Cxx/src/cxxstr.jl:191
 in macro expansion at /home/admin/.julia/v0.5/Cxx/src/cxxstr.jl:661 [inlined]
 in evaluate(::Function) at ./In[1]:11



#2

I found a way that seems to work, however I am still not sure if this is a sane solution?

function evaluate(f)
    f_void_ptr = cfunction(f, Void, ()) # void pointer on f. Need to cast it to function pointer
    icxx"""
    typedef void (*fptr)();
    fptr f_fun_ptr = reinterpret_cast<fptr>(reinterpret_cast<long>($f_void_ptr));
    evaluate(f_fun_ptr);
    """
end
f() = println("hi")
evaluate(f)
hi
g() = println("ho")
evaluate(g)
ho

#3

cfunction should be the way to go, yes, but I don’t understand why you need to cast to long first?


#4

Thanks! I guess the long cast is not necessary.


#5

It’s not only not necessary, it’s actively harmful: it will break e.g. on 64-bit Windows, where long if 4 bytes while pointers are 8 bytes.