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
>