-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Java.Interop] "Java Activation": API Declaration
Next can-o'-worms to start implementing: Java Activation: http://docs.xamarin.com/guides/android/under_the_hood/architecture/#Java_Activation There are logically two ways to create a "managed peer"/"native peer" instance pair: 1. By creating the managed peer, which will automagically create the native peer instance (see the JavaObject default constructor); or 2. By creating the native peer. (1) is implemented. (2) has not been, meaning at present if Java code were to create an instance of a "native peer", no corresponding managed peer instance would be created, and thus any `native` methods wouldn't be registered, and things would blow up rather quickly. How should this be exposed? Xamarin.Android has two related methods: * mono.android.Runtime.register(): registers native methods for a Java class. * mono.android.TypeManager.Activate(): invoked by the Java constructor, and responsible for associating the native peer with a managed peer, creating a new managed peer if necessary. The pattern for TypeManager.Activate() invocation is as follows: // Xamarin.Android constructor style public JavaPeerType(Args... args) { super (args...); if (getClass() == JavaPeerType.class) TypeManager.Activate ( AssemblyQualifiedTypeName, ConstructorSignature, this, new java.lang.Object[]{ args } ); } The need for the getClass() check is so that TypeManager.Activate() is only executed once, on the most derived native peer type, and not once per type in the inheritance chain. My feeling is that Runtime.register() and TypeManager.Activate() should be more closely related, because they both operate on peer types. (Runtime.register() is also a semantically poor name, and the it's only in Runtime for "where else should we put it?" reasons.) The alternative Java.Interop API? ManagedPeer.runConstructor() (and later, ManagedPeer.registerNativeMethods()), which also alters parameter ordering and now takes the Class for the declaring class: // Java.Interop constructor style: public JavaPeerType(Args... args) { super (args...); ManagedPeer.runConstructor ( JavaPeerType.class, this, AssemblyQualifiedTypeName, ConstructorSignature, args... ); } This "moves" the getClass() check into ManagedPeer.runConstructor(), allowing ManagedPeer methods to consistently take a Class instance, and also provides possible future flexibility on behavior. ManagedPeer.runConstructor() doesn't do anything at this time; this is just stubbing out the API, adding the appropriate calls to our Java "native peer" test types, and providing the initial C# implementation.
- Loading branch information
Showing
11 changed files
with
131 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
using System.Diagnostics; | ||
using System.Reflection; | ||
using System.Text; | ||
|
||
namespace Java.Interop { | ||
|
||
[JniTypeInfo (ManagedPeer.JniTypeName)] | ||
/* static */ class ManagedPeer : JavaObject { | ||
|
||
internal const string JniTypeName = "com/xamarin/android/ManagedPeer"; | ||
|
||
|
||
static readonly JniPeerMembers _members = new JniPeerMembers (JniTypeName, typeof (ManagedPeer)); | ||
|
||
static ManagedPeer () | ||
{ | ||
_members.JniPeerType.RegisterNativeMethods ( | ||
new JniNativeMethodRegistration ("runConstructor", RunConstructorSignature, (Action<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr>) RunConstructor) | ||
); | ||
} | ||
|
||
ManagedPeer () | ||
{ | ||
} | ||
|
||
internal static void Init () | ||
{ | ||
// Present so that JavaVM has _something_ to reference to | ||
// prompt invocation of the static constructor & registration | ||
} | ||
|
||
public override JniPeerMembers JniPeerMembers { | ||
get {return _members;} | ||
} | ||
|
||
const string RunConstructorSignature = "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V"; | ||
|
||
static void RunConstructor ( | ||
IntPtr jnienv, | ||
IntPtr klass, | ||
IntPtr n_self, | ||
IntPtr n_assemblyQualifiedName, | ||
IntPtr n_constructorSignature, | ||
IntPtr n_constructorArguments) | ||
{ | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
src/Java.Interop/Tests/java/com/xamarin/interop/CallNonvirtualDerived2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,13 @@ | ||
package com.xamarin.interop; | ||
|
||
public class CallNonvirtualDerived2 extends CallNonvirtualDerived { | ||
|
||
public CallNonvirtualDerived2 () { | ||
com.xamarin.android.ManagedPeer.runConstructor ( | ||
CallNonvirtualDerived2.class, | ||
this, | ||
"Java.InteropTests.CallNonvirtualDerived2, Java.Interop-Tests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", | ||
"" | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/Java.Interop/java/com/xamarin/android/ManagedPeer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.xamarin.android; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
public /* static */ class ManagedPeer { | ||
private ManagedPeer () { | ||
} | ||
|
||
// public static native void registerNativeMethods (java.lang.Class<?> nativeClass, String managedType, String methods); | ||
|
||
public static void runConstructor ( | ||
Class<?> declaringClass, | ||
Object self, | ||
String assemblyQualifiedName, | ||
String constructorSignature, | ||
Object... arguments) { | ||
if (self.getClass() != declaringClass) | ||
return; | ||
runConstructor (self, assemblyQualifiedName, constructorSignature, arguments); | ||
} | ||
|
||
static native void runConstructor ( | ||
Object self, | ||
String assemblyQualifiedName, | ||
String constructorSignature, | ||
Object... arguments | ||
); | ||
} |
@jonpryor I was looking at this last night.. Just a thought, currently Java.Interop is not dependent on Android as far as I can tell. do we really want to use an "android" package name here. perhaps com.xamarin.javainterop might be more generic.