On Mar 20, 2012, at 10:10 AM, Hänke, Maik wrote:

I suspect that the problem is that your native method wants `int lIdentifier`:

> public static native int Msg_UpdateOptions(int lIdentifier, boolean bEnabled, 
> boolean bQueue, String functionName, int convention, Object callBackObj);
>  
> I import the method with this code:
> public static int Msg_UpdateOptions(uint lIdentifier, bool bEnabled, bool 
> bQueue, String functionName, int convention, Java.Lang.Object callBackObj)

Yet you declared the parameter as `uint`. Java doesn't support uint, so when 
you construct a JValue around it:

>              new JValue(lIdentifier),

it will probably be invoking the JValue(long) constructor, not the JValue(int) 
constructor. The result, presumably, is that you're passing a long when an int 
is expected, and screwing up the stack.

I would suggest that you instead do:

        using (var _functionName = new Java.Lang.String(functionName))
                return JNIEnv.CallStaticIntMethod(mAlkClass, methodId, new 
JValue[] {
                                new JValue((int) lIdentifier),  // cast uint to 
int, so we don't implicitly convert uint to long
                                new JValue(bEnabled),
                                new JValue(bQueue),
                                new JValue(_functionName),
                                new JValue(convention),
                                new JValue(callBackObj)
                });

The `using` is so that we don't retain a gref for the string longer than 
necessary.

> In the Java sample the method is used in this way:
> Msg_UpdateOptions(AlkMsg.MSG_ID_TurnInstructions, true, false, 
> "OnTurnInstructionReceived", 0, this );
>  
> Where ‚this‘ is an activity and OnTurnInstructionReceived is a method of the 
> actvity.

This will be problematic, as what your Java library will have access to is the 
generated Android Callable Wrapper, which will not have a declaration for 
OnTurnInstructionReceived(). The result is that the method lookup will fail, 
presumably resulting in an exception at runtime.

The forthcoming (alpha!) 4.1 release will provide an [Export] custom attribute 
to support this scenario. In the meantime, you're probably looking at a painful 
world of declaring a Java-side interface and hand-writing a C# binding to that 
Java interface. For an example, see:

        
https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/Adder.java
        
https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/ManagedAdder.cs

For example, you'd need to add a TurnInstructionReceived.java file to your 
project, setting its build action to AndroidJavaSource:

        package demo;

        public interface TurnInstructionReceived {
                void OnTurnInstructionReceived(int buffer, int len);
        }

Then add a "fleshed out" version of a C# binding for the above Java interface:

        // see 
https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/ManagedAdder.cs#L82
        [Register("demo/TurnInstructionReceived", DoNotGenerateAcw=true)]
        interface ITurnInstructionReceived : Android.Runtime.IJavaObject {
                // Note: TODO_AQN is the AssemblyQualifiedName of the assembly 
containing this type.
                [Register ("OnTurnInstructionReceived", "(II)V", 
"GetOnTurnInstructionReceivedHandler: ITurnInstructionReceivedInvoker, 
TODO_AQN")]
                void OnTurnInstructionReceived(int buffer, int len);
        }

        class ITurnInstructionReceivedInvoker : Java.Lang.Object, 
ITurnInstructionReceived {
                // ...lots of stuff omitted...
                static Delegate cb_OnTurnInstructionReceived;
                static Delegate GetOnTurnInstructionReceivedHandler ()
                {
                        if (cb_OnTurnInstructionReceived == null)
                                cb_OnTurnInstructionReceived = 
JNINativeWrapper.CreateDelegate((Action<IntPtr, IntPtr, int, int>) 
n_OnTurnInstructionReceived);
                        return cb_OnTurnInstructionReceived;
                }

                static void n_OnTurnInstructionReceived(IntPtr jnienv, IntPtr 
lrefThis, int buffer, int len)
                {
                        ITurnInstructionReceived __this = 
Java.Lang.Object.GetObject<ITurnInstructionReceived >(lrefThis, 
JniHandleOwnership.DoNotTransfer);
                        __this.OnTurnInstructionReceived(buffer, len);
                }
        }

With the above two files, you could then modify your activity to implement 
ITurnInstructionReceived, allowing Msg_UpdateOptions() to invoke the 
OnTurnInstructionReceived() method.

 - Jon

_______________________________________________
Monodroid mailing list
Monodroid@lists.ximian.com

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid

Reply via email to