Skip to content

[Java.Interop] Add JniRuntime.JniValueManager.TryCreatePeer() #1301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions src/Java.Interop/Java.Interop/JniRuntime.JniValueManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,31 +336,21 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)

JniObjectReference.Dispose (ref targetClass);

var ctor = GetPeerConstructor (ref refClass, targetType);
if (ctor == null) {
var peer = CreatePeerInstance (ref refClass, targetType, ref reference, transfer);
if (peer == null) {
throw new NotSupportedException (string.Format ("Could not find an appropriate constructable wrapper type for Java type '{0}', targetType='{1}'.",
JniEnvironment.Types.GetJniTypeNameFromInstance (reference), targetType));
}

var acts = new object[] {
reference,
transfer,
};
try {
var peer = (IJavaPeerable) ctor.Invoke (acts);
peer.SetJniManagedPeerState (peer.JniManagedPeerState | JniManagedPeerStates.Replaceable);
return peer;
} finally {
reference = (JniObjectReference) acts [0];
}
peer.SetJniManagedPeerState (peer.JniManagedPeerState | JniManagedPeerStates.Replaceable);
return peer;
}

static readonly Type ByRefJniObjectReference = typeof (JniObjectReference).MakeByRefType ();

ConstructorInfo? GetPeerConstructor (
IJavaPeerable? CreatePeerInstance (
ref JniObjectReference klass,
[DynamicallyAccessedMembers (Constructors)]
Type fallbackType)
Type fallbackType,
ref JniObjectReference reference,
JniObjectReferenceOptions transfer)
{
var jniTypeName = JniEnvironment.Types.GetJniTypeNameFromClass (klass);

Expand All @@ -373,11 +363,12 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)
type = Runtime.TypeManager.GetType (sig);

if (type != null) {
var ctor = GetActivationConstructor (type);
type = GetInvokerType (type) ?? type;
var peer = TryCreatePeer (ref reference, transfer, type);

if (ctor != null) {
if (peer != null) {
JniObjectReference.Dispose (ref klass);
return ctor;
return peer;
}
}

Expand All @@ -391,20 +382,29 @@ static Type GetPeerType ([DynamicallyAccessedMembers (Constructors)] Type type)
}
JniObjectReference.Dispose (ref klass, JniObjectReferenceOptions.CopyAndDispose);

return GetActivationConstructor (fallbackType);
return TryCreatePeer (ref reference, transfer, fallbackType);
}

static ConstructorInfo? GetActivationConstructor (
const BindingFlags ActivationConstructorBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
static readonly Type ByRefJniObjectReference = typeof (JniObjectReference).MakeByRefType ();
static readonly Type[] JIConstructorSignature = new Type [] { ByRefJniObjectReference, typeof (JniObjectReferenceOptions) };


protected virtual IJavaPeerable? TryCreatePeer (
ref JniObjectReference reference,
JniObjectReferenceOptions options,
[DynamicallyAccessedMembers (Constructors)]
Type type)
{
if (type.IsAbstract || type.IsInterface) {
type = GetInvokerType (type) ?? type;
}
foreach (var c in type.GetConstructors (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
var p = c.GetParameters ();
if (p.Length == 2 && p [0].ParameterType == ByRefJniObjectReference && p [1].ParameterType == typeof (JniObjectReferenceOptions))
return c;
var c = type.GetConstructor (ActivationConstructorBindingFlags, null, JIConstructorSignature, null);
if (c != null) {
var args = new object[] {
reference,
options,
};
var p = (IJavaPeerable) c.Invoke (args);
reference = (JniObjectReference) args [0];
return p;
}
return null;
}
Expand Down
1 change: 1 addition & 0 deletions src/Java.Interop/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ static Java.Interop.JniEnvironment.BeginMarshalMethod(nint jnienv, out Java.Inte
static Java.Interop.JniEnvironment.EndMarshalMethod(ref Java.Interop.JniTransition transition) -> void
virtual Java.Interop.JniRuntime.OnEnterMarshalMethod() -> void
virtual Java.Interop.JniRuntime.OnUserUnhandledException(ref Java.Interop.JniTransition transition, System.Exception! e) -> void
virtual Java.Interop.JniRuntime.JniValueManager.TryCreatePeer(ref Java.Interop.JniObjectReference reference, Java.Interop.JniObjectReferenceOptions options, System.Type! type) -> Java.Interop.IJavaPeerable?
Java.Interop.JavaException.JavaException(ref Java.Interop.JniObjectReference reference, Java.Interop.JniObjectReferenceOptions transfer, Java.Interop.JniObjectReference throwableOverride) -> void
Java.Interop.JavaException.SetJavaStackTrace(Java.Interop.JniObjectReference peerReferenceOverride = default(Java.Interop.JniObjectReference)) -> void
Java.Interop.JniRuntime.JniValueManager.GetPeer(Java.Interop.JniObjectReference reference, System.Type? targetType = null) -> Java.Interop.IJavaPeerable?
Expand Down
Loading