Skip to content
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

[Java.Interop] Add JniMemberInfoLookup #1208

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions src/Java.Interop/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

// See: 045b8af7, 6a42bb89, f60906cf, e10f7cb0, etc.
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.Exceptions")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.InstanceFields")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.InstanceMethods")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.StaticFields")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniEnvironment.StaticMethods")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniPeerMembers.JniStaticMethods")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniRuntime.JniMarshalMemberBuilder")]
[assembly: SuppressMessage ("Design", "CA1034:Nested types should not be visible", Justification = "Deliberate choice to 'hide' these types from code completion for `Java.Interop.`.", Scope = "type", Target = "~T:Java.Interop.JniPeerMembers.JniStaticFields")]
Expand Down
2 changes: 1 addition & 1 deletion src/Java.Interop/Java.Interop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<OutputPath>$(ToolOutputFullPath)</OutputPath>
<DocumentationFile>$(ToolOutputFullPath)Java.Interop.xml</DocumentationFile>
<JNIEnvGenPath>$(BuildToolOutputFullPath)</JNIEnvGenPath>
<LangVersion Condition=" '$(JIBuildingForNetCoreApp)' == 'True' ">9.0</LangVersion>
<LangVersion Condition=" '$(JIBuildingForNetCoreApp)' == 'True' ">12.0</LangVersion>
<LangVersion Condition=" '$(LangVersion)' == '' ">8.0</LangVersion>
<Version>$(JICoreLibVersion)</Version>
<Standalone Condition=" '$(Standalone)' == '' ">true</Standalone>
Expand Down
37 changes: 37 additions & 0 deletions src/Java.Interop/Java.Interop/JniEnvironment.InstanceFields.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;

namespace Java.Interop;

partial class JniEnvironment {
partial class InstanceFields {
public static unsafe JniFieldInfo GetFieldID (JniObjectReference type, ReadOnlySpan<byte> name, ReadOnlySpan<byte> signature)
{
if (!type.IsValid)
throw new ArgumentException ("Handle must be valid.", "type");

IntPtr env = JniEnvironment.EnvironmentPointer;
IntPtr field;
IntPtr thrown;
fixed (void* name_ptr = &MemoryMarshal.GetReference (name))
fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) {
field = JniNativeMethods.GetFieldID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr);
thrown = JniNativeMethods.ExceptionOccurred (env);
}

Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown);
if (__e != null)
ExceptionDispatchInfo.Capture (__e).Throw ();

if (field == IntPtr.Zero)
throw new InvalidOperationException ("Should not be reached; `GetFieldID` should have thrown!");

#if DEBUG
return new JniFieldInfo (name.ToString (), signature.ToString (), field, isStatic: false);
#else // DEBUG
return new JniFieldInfo (null!, null!, field, isStatic: false);
#endif // DEBUG
}
}
}
37 changes: 37 additions & 0 deletions src/Java.Interop/Java.Interop/JniEnvironment.InstanceMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;

namespace Java.Interop;

partial class JniEnvironment {
partial class InstanceMethods {
public static unsafe JniMethodInfo GetMethodID (JniObjectReference type, ReadOnlySpan<byte> name, ReadOnlySpan<byte> signature)
{
if (!type.IsValid)
throw new ArgumentException ("Handle must be valid.", "type");

IntPtr env = JniEnvironment.EnvironmentPointer;
IntPtr method;
IntPtr thrown;
fixed (void* name_ptr = &MemoryMarshal.GetReference (name))
fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) {
method = JniNativeMethods.GetMethodID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr);
thrown = JniNativeMethods.ExceptionOccurred (env);
}

Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown);
if (__e != null)
ExceptionDispatchInfo.Capture (__e).Throw ();

if (method == IntPtr.Zero)
throw new InvalidOperationException ("Should not be reached; `GetMethodID` should have thrown!");

#if DEBUG
return new JniMethodInfo (name.ToString (), signature.ToString (), method, isStatic: false);
#else // DEBUG
return new JniMethodInfo (null!, null!, method, isStatic: false);
#endif // DEBUG
}
}
}
38 changes: 38 additions & 0 deletions src/Java.Interop/Java.Interop/JniEnvironment.StaticFields.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;

namespace Java.Interop;

partial class JniEnvironment {
partial class StaticFields {

public static unsafe JniFieldInfo GetStaticFieldID (JniObjectReference type, ReadOnlySpan<byte> name, ReadOnlySpan<byte> signature)
{
if (!type.IsValid)
throw new ArgumentException ("Handle must be valid.", "type");

IntPtr env = JniEnvironment.EnvironmentPointer;
IntPtr field;
IntPtr thrown;
fixed (void* name_ptr = &MemoryMarshal.GetReference (name))
fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) {
field = JniNativeMethods.GetStaticFieldID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr);
thrown = JniNativeMethods.ExceptionOccurred (env);
}

Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown);
if (__e != null)
ExceptionDispatchInfo.Capture (__e).Throw ();

if (field == IntPtr.Zero)
throw new InvalidOperationException ("Should not be reached; `GetFieldID` should have thrown!");

#if DEBUG
return new JniFieldInfo (name.ToString (), signature.ToString (), field, isStatic: false);
#else // DEBUG
return new JniFieldInfo (null!, null!, field, isStatic: false);
#endif // DEBUG
}
}
}
82 changes: 82 additions & 0 deletions src/Java.Interop/Java.Interop/JniEnvironment.StaticMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;

namespace Java.Interop;

partial class JniEnvironment {
partial class StaticMethods {

public static unsafe JniMethodInfo GetStaticMethodID (JniObjectReference type, ReadOnlySpan<byte> name, ReadOnlySpan<byte> signature)
{
if (!type.IsValid)
throw new ArgumentException ("Handle must be valid.", "type");

IntPtr env = JniEnvironment.EnvironmentPointer;
IntPtr method;
IntPtr thrown;
fixed (void* name_ptr = &MemoryMarshal.GetReference (name))
fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) {
method = JniNativeMethods.GetStaticMethodID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr);
thrown = JniNativeMethods.ExceptionOccurred (env);
}

Exception? __e = JniEnvironment.GetExceptionForLastThrowable (thrown);
if (__e != null)
ExceptionDispatchInfo.Capture (__e).Throw ();

if (method == IntPtr.Zero)
throw new InvalidOperationException ("Should not be reached; `GetStaticMethodID` should have thrown!");

#if DEBUG
return new JniMethodInfo (name.ToString (), signature.ToString (), method, isStatic: true);
#else // DEBUG
return new JniMethodInfo (null!, null!, method, isStatic: true);
#endif // DEBUG
}

internal static unsafe bool TryGetStaticMethod (
JniObjectReference type,
ReadOnlySpan<byte> name,
ReadOnlySpan<byte> signature,
[NotNullWhen(true)]
out JniMethodInfo? method)
{
method = null;

if (!type.IsValid)
throw new ArgumentException ("Handle must be valid.", "type");

IntPtr env = JniEnvironment.EnvironmentPointer;
IntPtr id;
IntPtr thrown;
fixed (void* name_ptr = &MemoryMarshal.GetReference (name))
fixed (void* signature_ptr = &MemoryMarshal.GetReference (signature)) {
id = JniNativeMethods.GetStaticMethodID (env, type.Handle, (IntPtr) name_ptr, (IntPtr) signature_ptr);
thrown = JniNativeMethods.ExceptionOccurred (env);
}

if (thrown != IntPtr.Zero) {
JniNativeMethods.ExceptionClear (env);
JniEnvironment.References.RawDeleteLocalRef (env, thrown);
thrown = IntPtr.Zero;
return false;
}

Debug.Assert (id != IntPtr.Zero);
if (id == IntPtr.Zero) {
return false;
}

#if DEBUG
method = new JniMethodInfo (name.ToString (), signature.ToString (), id, isStatic: true);
#else // DEBUG
method = new JniMethodInfo (null!, null!, id, isStatic: true);
#endif // DEBUG

return true;
}
}
}
22 changes: 22 additions & 0 deletions src/Java.Interop/Java.Interop/JniMemberInfoLookup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace Java.Interop;

public ref struct JniMemberInfoLookup {
public string EncodedMember {get; private set;}
public ReadOnlySpan<byte> MemberName {get; private set;}
public ReadOnlySpan<byte> MemberSignature {get; private set;}

[Obsolete ("Use the JniMemberInfoLookup(string, ReadOnlySpan<byte>, ReadOnlySpan<byte>) constructor.", error: true)]
public JniMemberInfoLookup ()
{
throw new NotSupportedException ();
}

public JniMemberInfoLookup (string encodedMember, ReadOnlySpan<byte> memberName, ReadOnlySpan<byte> memberSignature)
{
EncodedMember = encodedMember;
MemberName = memberName;
MemberSignature = memberSignature;
}
}
Loading