I'd like to bump this and see if anyone has any ideas. I do not see what could change.
To provide some background, if it would help, The code referenced by Eric runs at load time, to generate a set of methods (called _jcall) for different types of inputs. For each such input type, a method definition is created within a quote block, and then that quote block is eval-ed to actually define the method. The reason separate functions are defined, rather than doing this by dynamic dispatch, is that a key part of the method is a ccall. The argument types to the ccall needs to be determined at compile time, and hence in this case we define a separate method for each input type, rather than use dynamic dispatch. This code works correctly in 0.4 (and 0.3), but fails with an UndefRefError in 0.5. Any ideas? Thanks! - Avik On Friday, 24 June 2016 19:50:01 UTC+1, Eric Davies wrote: > > I have an intuition that this should be possible because the ccall depends > on the input types, but I can't figure out how to make it work. I've tried > a few things and they all seem to result in an UndefVarError or > UndefRefError. > > I want to turn this: > for (x, y, z) in [ (:jboolean, :(jnifunc.CallBooleanMethodA), :(jnifunc. > CallStaticBooleanMethodA)), > (:jchar, :(jnifunc.CallCharMethodA), :(jnifunc. > CallStaticCharMethodA)), > (:jbyte, :(jnifunc.CallByteMethodA), :(jnifunc. > CallStaticByteMethodA)), > (:jshort, :(jnifunc.CallShortMethodA), :(jnifunc. > CallStaticShortMethodA)), > (:jint, :(jnifunc.CallIntMethodA), :(jnifunc. > CallStaticIntMethodA)), > (:jlong, :(jnifunc.CallLongMethodA), :(jnifunc. > CallStaticLongMethodA)), > (:jfloat, :(jnifunc.CallFloatMethodA), :(jnifunc. > CallStaticFloatMethodA)), > (:jdouble, :(jnifunc.CallDoubleMethodA), :(jnifunc. > CallStaticDoubleMethodA)), > (:Void, :(jnifunc.CallVoidMethodA), :(jnifunc. > CallStaticVoidMethodA)) ] > m = quote > function _jcall(obj, jmethodId::Ptr{Void}, callmethod::Ptr{Void}, > rettype::Type{$(x)}, argtypes::Tuple, args... ) > if callmethod == C_NULL #! > callmethod = ifelse( typeof(obj)<:JavaObject, $y , $z ) > end > @assert callmethod != C_NULL > @assert jmethodId != C_NULL > if(isnull(obj)); error("Attempt to call method on Java NULL"); > end > savedArgs, convertedArgs = convert_args(argtypes, args...) > result = ccall(callmethod, $x , (Ptr{JNIEnv}, Ptr{Void}, Ptr{ > Void}, Ptr{Void}), penv, obj.ptr, jmethodId, convertedArgs) > if result==C_NULL; geterror(); end > if result == nothing; return; end > return convert_result(rettype, result) > end > end > eval(m) > end > > Into something that works on 0.5. Code located here: > https://github.com/invenia/JavaCall.jl/blob/compat-0.5/src/core.jl#L196 > > I've learned tricks to deal with the 0.4 function eval pattern, but they > don't seem to work with ccall, which is a special feature that requires > some arguments to be static and known at compile time. > > Anyone have any tips? > > Thanks, > Eric >