fcknbstrd 0 Posted October 27, 2019 Hello, I'm getting an error log message (Android Device Monitor) in my Android app built with Delphi 10.3.2, tested on a Nokia 7 (Android 9) and NVIDIA Shield K1 tablet (Android 7): java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: the return type of CallVoidMethodV does not match void cn.easyar.FunctorOfVoidFromTargetAndBool.invoke(cn.easyar.Target, boolean) I'm building an AR framework with an external library and it crashes when I try to load an image target for AR detection. The weird thing is: that I have an older project (created with 10.3.1) where the framework runs successfully, ... but only on the Shield tablet (Android 7). But when creating a new project with 10.3.2 my framework do not run on any device. Is there any difference in project files, that could have influence? The method signature seems okey to me for a CallVoidMethodV call. The interface is declared in third party JAR as: package cn.easyar; public interface FunctorOfVoidFromTargetAndBool { void invoke(Target paramTarget, boolean paramBoolean); } The interface declaration in Delphi JNI file, looks like: JFunctorOfVoidFromTargetAndBoolClass = interface(IJavaClass) ['{A269080B-630F-428F-987C-B8B611A82E57}'] end; [JavaSignature('cn/easyar/FunctorOfVoidFromTargetAndBool')] JFunctorOfVoidFromTargetAndBool = interface(IJavaInstance) ['{CA02CD6D-7C69-43CA-B5C4-53C65761EEA0}'] {class} procedure invoke(P1: Jeasyar_Target; P2: Boolean); cdecl; end; TJFunctorOfVoidFromTargetAndBool = class(TJavaGenericImport<JFunctorOfVoidFromTargetAndBoolClass, JFunctorOfVoidFromTargetAndBool>) end; It seems to be a callback, so I declared a TJavaLocal, like this: TFunctorOfVoidFromTargetAndBoolProxy = class(TJavaLocal, JFunctorOfVoidFromTargetAndBool) protected public constructor Create(); { JFunctorOfVoidFromTargetAndBool } procedure invoke(P1: Jeasyar_Target; P2: Boolean); cdecl; end; { Implementation of JavaLocal } constructor TFunctorOfVoidFromTargetAndBoolProxy.Create(); begin inherited Create(); end; procedure TFunctorOfVoidFromTargetAndBoolProxy.invoke(P1: Jeasyar_Target; P2: Boolean); cdecl; begin if P2 then FMX.Types.Log.D('target ' + JStringToString(P1.name) + ' loaded') else FMX.Types.Log.D('failed to load target ' + JStringToString(P1.name)); end; The functor is getting used the following way: FOnLoadTarget := TJFunctorOfVoidFromTargetAndBool.Wrap( (TFunctorOfVoidFromTargetAndBoolProxy.Create() as ILocalObject).GetObjectID() ); // loading the target with callback FTracker.LoadTarget(FTarget, FScheduler, FOnLoadTarget); Used fields are declared like that: // field declarations [...] FScheduler : JDelayedCallbackScheduler; // inherited from JCallbackScheduler FTracker : JImageTracker; FTarget : JImageTarget; // inherited from Jeasyar_Target FOnLoadTarget : JFunctorOfVoidFromTargetAndBool; [...] The tracker "loadTarget" method is declared as: JImageTrackerClass = interface(JRefBaseClass) ['{CCD92F4A-618D-420A-8AF5-240051B51A73}'] {...} end; [JavaSignature('cn/easyar/ImageTracker')] JImageTracker = interface(JRefBase) ['{CD917C43-91DD-4602-9683-82EFC85F5988}'] {...} procedure loadTarget(P1: Jeasyar_Target; P2: JCallbackScheduler; P3: JFunctorOfVoidFromTargetAndBool); cdecl; {...} end; TJImageTracker = class(TJavaGenericImport<JImageTrackerClass, JImageTracker>) end; Remarks: The "loadTarget" method is loading an image file as target asynchronously in a separate thread. I would be pleased if anyone has an idea on that, because I'm stucked for a while now :) (Notice: I attached the complete logfile output for more details.) log-nokia2.txt Share this post Link to post
fcknbstrd 0 Posted October 31, 2019 I found a solution myself. I've built a separate JavaClass lib which accesses the AR-JAR. I call loadTarget() inside of Java, to prevent creating a TJavaLocal in Delphi. There seems to be a problem with TJavaLocal (ProxyInterface / InvocationHandler) in new compilers. Because the 3rd party AR-suite declares callback interfaces with an "invoke" callback method: package cn.easyar; public interface FunctorOfVoidFromTargetAndBool { void invoke(Target paramTarget, boolean paramBoolean); } The call on FunctorOfVoidFromTargetAndBool.invoke (performed by the 3rd party library, using JNI) leads to a method collision, because InvocationHandler itself declares also an "invoke" method. JNI picks the wrong "invoke" method which leads to the error message: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: the return type of CallVoidMethodV does not match void cn.easyar.FunctorOfVoidFromTargetAndBool.invoke(cn.easyar.Target, boolean) Share this post Link to post
Remy Lebeau 1396 Posted November 1, 2019 On 10/31/2019 at 6:23 AM, fcknbstrd said: There seems to be a problem with TJavaLocal (ProxyInterface / InvocationHandler) in new compilers. Feel free to file a bug report with Embarcadero. Share this post Link to post
fcknbstrd 0 Posted November 4, 2019 https://quality.embarcadero.com/browse/RSP-26575 Done 🙂 Share this post Link to post