Skip to content

[Hello-NativeAOTFromJNI] Add NativeAOT sample #1153

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 52 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
007317b
[Hello-NativeAOTFromJNI] Add NativeAOT sample
jonpryor Oct 24, 2023
db84cc3
Try to create a JreRuntime
jonpryor Oct 25, 2023
a32e244
icanhaz blittable method registration?
jonpryor Oct 25, 2023
4c30ab5
Linux builds require -Wl,-soname to be set properly.
jonpryor Oct 25, 2023
a08dce8
Fix build break.
jonpryor Oct 25, 2023
da9f188
Use [UnmanagedFunctionPointer]
jonpryor Oct 25, 2023
69c90ba
"Full(er)" sample
jonpryor Nov 1, 2023
1fc0af5
Use JniTransition.
jonpryor Nov 2, 2023
a499a1d
Allow init from JNIEnv*, not just JavaVM*
jonpryor Nov 2, 2023
e1822f0
Make it (mostly) work!
jonpryor Nov 2, 2023
9027591
Fix Java.Interop.Export-Tests
jonpryor Nov 7, 2023
1d422da
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Nov 7, 2023
902fe28
Remove more `n_`s?!
jonpryor Nov 7, 2023
0392169
Enable activation
jonpryor Nov 7, 2023
93a901a
Allow marking constructors as callable from Java.
jonpryor Nov 7, 2023
a50457b
Partially revert 9027591c41232c82a582f8ab16ddaa783795582c
jonpryor Nov 8, 2023
ce850ca
Rethink `Type.GetType()` alternatives
jonpryor Nov 9, 2023
6920e6c
Remove need for NativeAotValueManager.
jonpryor Nov 9, 2023
4ceaa34
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Nov 13, 2023
cf73d77
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Nov 14, 2023
986f0c4
Reduce patch size.
jonpryor Nov 14, 2023
17a4403
Work with .NET 8 GA (…?)
jonpryor Nov 15, 2023
1b86f9a
Use `net.dot.jni` package prefix
jonpryor Nov 16, 2023
f71cadb
Forgot to fix up a header path…
jonpryor Nov 16, 2023
b5fc4cf
Don't add new public API
jonpryor Nov 16, 2023
4741dc9
Reduce patch size.
jonpryor Nov 16, 2023
8eb2850
Remove more unneeded bits.
jonpryor Nov 16, 2023
c3e4870
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Nov 23, 2023
aeed449
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Nov 24, 2023
1e71988
Remove GetTypeFromAssemblyQualifiedName()
jonpryor Nov 23, 2023
1b7be6c
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Dec 2, 2023
14f6713
Cleanup.
jonpryor Dec 3, 2023
508dcde
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Feb 9, 2024
74248fb
Merge remote-tracking branch 'origin/main' into dev/jonp/jonp-hello-f…
jonpryor Feb 16, 2024
12e187e
Fix spelling of JNI_OnUnload
jonpryor Feb 16, 2024
cfdfeaf
Reduce unnecessary changes.
jonpryor Feb 16, 2024
0803048
Integrate Hello-NativeAOTFromJNI.csproj into Java.Interop.sln
jonpryor Feb 16, 2024
f8bb97f
Cleanup.
jonpryor Feb 16, 2024
12cda04
Run the sample on CI!
jonpryor Feb 16, 2024
3861773
Reduce manual string duplication.
jonpryor Feb 16, 2024
adf5773
Remove unnecessary line.
jonpryor Feb 16, 2024
65f7d90
Set publishWebProjects: false.
jonpryor Feb 16, 2024
429bb4d
Try setting workingDirectory.
jonpryor Feb 16, 2024
b4cddb7
Setting workingDirectory didn't fix things.
jonpryor Feb 16, 2024
42c7251
$CWD isn't what I expect, so use a rooted WorkingDirectory.
jonpryor Feb 16, 2024
f656870
MOAR PRINTFS
jonpryor Feb 16, 2024
1b8b1af
Avoid DotNetCoreCLI@2
jonpryor Feb 16, 2024
59314fc
Cleanup.
jonpryor Feb 16, 2024
2a012c7
Fix some `dotnet publish` linker warnings.
jonpryor Feb 16, 2024
f79d3e1
Quote `$(DotnetToolPath)`, as it will contain spaces on Windows.
jonpryor Feb 16, 2024
213a57b
$(Standalone) by default, and prefer `native-library` loader in JreRu…
jonpryor Feb 16, 2024
cf240f9
Run the Hello-NativeAOT tests on Windows, too
jonpryor Feb 16, 2024
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
Prev Previous commit
Next Next commit
Partially revert 9027591
Remember 902fe28?

> Assuming it works on CI, next step will be to largely revert
> 9027591, and then fix
> `Java.Interop.Export-Tests` to use an `n_` prefix on all `native`
> method declarations.  That bit is hand-written; it can change.
> Keeping the tooling consistent is more important.

Let's Do It!  Revert most of the `JavaCallableWrapperGenerator`
bits of 9027591.

Update the `JavaInterop1` JCW output to conform, using `n_`-prefixed
native method declarations.

*Retain the constructor signature fix* in 93a901a..

Revert the `JreTypeManager` change in 902fe28.

Update `jnimarshalmethod-gen` to register `n_`-prefixed names.

Update `Java.Interop.Export-Tests` so that native method declarations
now have `n_` prefixes, so that all is in sync.
  • Loading branch information
jonpryor committed Nov 8, 2023
commit a50457be6517921f77f4cf3307d09c25588803a1
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public JniNativeMethodRegistration CreateMarshalToManagedMethodRegistration (Jav

string GetJniMethodName (JavaCallableAttribute export, MethodInfo method)
{
return export.Name ?? "n_" + method.Name;
return "n_" + method.Name;
}

public string GetJniMethodSignature (JavaCallableAttribute export, MethodInfo method)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,6 @@ void AddNestedTypes (TypeDefinition type)
type.IsSubclassOf ("Android.Content.ContentProvider", cache)))
Diagnostic.Error (4203, LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4203, jniName);

this.outerType = outerType;
}

bool initialized;
string? outerType;

void Initialize ()
{
if (initialized)
return;
initialized = true;

foreach (MethodDefinition minfo in type.Methods.Where (m => !m.IsConstructor)) {
var baseRegisteredMethod = GetBaseRegisteredMethod (minfo);
if (baseRegisteredMethod != null)
Expand Down Expand Up @@ -313,9 +301,7 @@ void AddConstructor (MethodDefinition ctor, TypeDefinition type, string? outerTy
if (!string.IsNullOrEmpty (eattr.Name)) {
// Diagnostic.Warning (log, "Use of ExportAttribute.Name property is invalid on constructors");
}
ctors.Add (new Signature (new (cache, CodeGenerationTarget, ctor, eattr) {
ManagedParameters = managedParameters,
}));
ctors.Add (new Signature (ctor, eattr, managedParameters, cache));
curCtors.Add (ctor);
return;
}
Expand All @@ -324,10 +310,7 @@ void AddConstructor (MethodDefinition ctor, TypeDefinition type, string? outerTy
if (rattr != null) {
if (ctors.Any (c => c.JniSignature == rattr.Signature))
return;
ctors.Add (new Signature (new (cache, CodeGenerationTarget, ctor, rattr) {
ManagedParameters = managedParameters,
OuterType = outerType,
}));
ctors.Add (new Signature (ctor, rattr, managedParameters, outerType, cache));
curCtors.Add (ctor);
return;
}
Expand All @@ -348,26 +331,12 @@ void AddConstructor (MethodDefinition ctor, TypeDefinition type, string? outerTy
}

if (baseCtors.Any (m => m.Parameters.AreParametersCompatibleWith (ctor.Parameters, cache))) {
ctors.Add (new Signature (new (cache, CodeGenerationTarget) {
RegisterName = ".ctor",
RegisterSignature = jniSignature,
RegisterConnector = "",
ManagedParameters = managedParameters,
OuterType = outerType,
IsDynamicallyRegistered = true,
}));
ctors.Add (new Signature (".ctor", jniSignature, "", managedParameters, outerType, null));
curCtors.Add (ctor);
return;
}
if (baseCtors.Any (m => !m.HasParameters)) {
ctors.Add (new Signature (new (cache, CodeGenerationTarget) {
RegisterName = ".ctor",
RegisterSignature = jniSignature,
RegisterConnector = "",
ManagedParameters = managedParameters,
OuterType = outerType,
IsDynamicallyRegistered = true,
}));
ctors.Add (new Signature (".ctor", jniSignature, "", managedParameters, outerType, ""));
curCtors.Add (ctor);
return;
}
Expand Down Expand Up @@ -533,17 +502,15 @@ void AddMethod (MethodDefinition? registeredMethod, MethodDefinition implemented
Diagnostic.Error (4217, LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4217, attr.Name);

bool shouldBeDynamicallyRegistered = methodClassifier?.ShouldBeDynamicallyRegistered (type, registeredMethod, implementedMethod, attr.OriginAttribute) ?? true;
var msig = new Signature (new (cache, CodeGenerationTarget, implementedMethod, attr) {
IsDynamicallyRegistered = shouldBeDynamicallyRegistered,
});
var msig = new Signature (implementedMethod, attr, cache, shouldBeDynamicallyRegistered);
if (!registeredMethod.IsConstructor && !methods.Any (m => m.Name == msig.Name && m.Params == msig.Params))
methods.Add (msig);
}
foreach (ExportAttribute attr in GetExportAttributes (implementedMethod)) {
if (type.HasGenericParameters)
Diagnostic.Error (4206, LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4206);

var msig = new Signature (new (cache, CodeGenerationTarget, implementedMethod, attr));
var msig = new Signature (implementedMethod, attr, null, cache);
if (!string.IsNullOrEmpty (attr.SuperArgumentsString)) {
// Diagnostic.Warning (log, "Use of ExportAttribute.SuperArgumentsString property is invalid on methods");
}
Expand All @@ -554,7 +521,7 @@ void AddMethod (MethodDefinition? registeredMethod, MethodDefinition implemented
if (type.HasGenericParameters)
Diagnostic.Error (4207, LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4207);

var msig = new Signature (new (cache, CodeGenerationTarget, implementedMethod, attr));
var msig = new Signature (implementedMethod, attr, cache);
if (!implementedMethod.IsConstructor && !methods.Any (m => m.Name == msig.Name && m.Params == msig.Params)) {
methods.Add (msig);
exported_fields.Add (new JavaFieldInfo (implementedMethod, attr.Name, cache));
Expand Down Expand Up @@ -603,8 +570,6 @@ string GetManagedParameters (MethodDefinition ctor, string? outerType)

public void Generate (TextWriter writer)
{
Initialize ();

if (!string.IsNullOrEmpty (package)) {
writer.WriteLine ("package " + package + ";");
writer.WriteLine ();
Expand Down Expand Up @@ -821,7 +786,7 @@ void GenerateRegisterType (TextWriter sw, JavaCallableWrapperGenerator self, str

foreach (Signature method in self.methods) {
if (method.IsDynamicallyRegistered) {
sw.Write ("\t\t\t\"");
sw.Write ("\t\t\t\"", method.Method);
sw.Write (method.Method);
sw.WriteLine ("\\n\" +");
}
Expand Down Expand Up @@ -887,121 +852,66 @@ bool CannotRegisterInStaticConstructor (TypeDefinition type)
return JavaNativeTypeManager.IsApplication (type, cache) || JavaNativeTypeManager.IsInstrumentation (type, cache);
}

record struct SignatureOptions (IMetadataResolver Cache, JavaPeerStyle Style) {
class Signature {

public SignatureOptions (IMetadataResolver cache, JavaPeerStyle style, MethodDefinition method)
: this (cache, style)
{
Method = method;
IsStatic = method.IsStatic;
JavaAccess = JavaCallableWrapperGenerator.GetJavaAccess (method.Attributes & MethodAttributes.MemberAccessMask);
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", method.CustomAttributes, cache);
IsDynamicallyRegistered = true;
}
public Signature (MethodDefinition method, RegisterAttribute register, IMetadataResolver cache, bool shouldBeDynamicallyRegistered = true) : this (method, register, null, null, cache, shouldBeDynamicallyRegistered) {}

public SignatureOptions (IMetadataResolver cache, JavaPeerStyle style, MethodDefinition method, RegisterAttribute register)
: this (cache, style, method)
public Signature (MethodDefinition method, RegisterAttribute register, string? managedParameters, string? outerType, IMetadataResolver cache, bool shouldBeDynamicallyRegistered = true)
: this (register.Name, register.Signature, register.Connector, managedParameters, outerType, null)
{
Register = register;
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", method.CustomAttributes, cache);
IsDynamicallyRegistered = shouldBeDynamicallyRegistered;
}

public SignatureOptions (IMetadataResolver cache, JavaPeerStyle style, MethodDefinition method, ExportAttribute export)
: this (cache, style, method)
public Signature (MethodDefinition method, ExportAttribute export, string? managedParameters, IMetadataResolver cache)
: this (method.Name, GetJniSignature (method, cache), "__export__", null, null, export.SuperArgumentsString)
{
IsExport = true;
SuperCall = export.SuperArgumentsString;
ThrownTypeNames = export.ThrownNames;
JavaNameOverride = export.Name;
if (style == JavaPeerStyle.JavaInterop1) {
RegisterName = export.Name;
}
IsExport = true;
IsStatic = method.IsStatic;
JavaAccess = JavaCallableWrapperGenerator.GetJavaAccess (method.Attributes & MethodAttributes.MemberAccessMask);
ThrownTypeNames = export.ThrownNames;
JavaNameOverride = export.Name;
ManagedParameters = managedParameters;
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", method.CustomAttributes, cache);
}

public SignatureOptions (IMetadataResolver cache, JavaPeerStyle style, MethodDefinition method, ExportFieldAttribute exportField)
: this (cache, style, method)
public Signature (MethodDefinition method, ExportFieldAttribute exportField, IMetadataResolver cache)
: this (method.Name, GetJniSignature (method, cache), "__export__", null, null, null)
{
IsExport = true;
Annotations = null;

if (method.HasParameters)
Diagnostic.Error (4205, JavaCallableWrapperGenerator.LookupSource (method), Localization.Resources.JavaCallableWrappers_XA4205);
if (method.ReturnType.MetadataType == MetadataType.Void)
Diagnostic.Error (4208, JavaCallableWrapperGenerator.LookupSource (method), Localization.Resources.JavaCallableWrappers_XA4208);
}

IsExport = true;
IsStatic = method.IsStatic;
JavaAccess = JavaCallableWrapperGenerator.GetJavaAccess (method.Attributes & MethodAttributes.MemberAccessMask);

public string? RegisterName;
public string? RegisterSignature;
public string? RegisterConnector;
public RegisterAttribute Register {
set {
RegisterName = value.Name;
RegisterSignature = value.Signature;
RegisterConnector = value.Connector;
}
}
public MethodDefinition Method {
set {
RegisterName = value.Name;
RegisterSignature = GetJniSignature (value, Cache);
RegisterConnector = "__export__";
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", value.CustomAttributes, Cache);
}
// annotations are processed within JavaFieldInfo, not the initializer method. So we don't generate them here.
}
public bool IsDynamicallyRegistered;
public string? ManagedParameters;
public string? OuterType;
public string? SuperCall;
public string? Annotations;
public string? JavaAccess;
public string? JavaNameOverride;
public bool IsExport;
public bool IsStatic;
public string[]? ThrownTypeNames;
}

class Signature {

public Signature (SignatureOptions options)
public Signature (string name, string? signature, string? connector, string? managedParameters, string? outerType, string? superCall)
{
if (options.RegisterName == null) {
throw new ArgumentNullException ("`RegisterName` cannot be null.", nameof (options.RegisterName));
}
if (options.RegisterSignature == null) {
throw new ArgumentNullException ("`RegisterSignature` cannot be null.", nameof (options.RegisterSignature));
}
Annotations = options.Annotations;
IsDynamicallyRegistered = options.IsDynamicallyRegistered;
IsExport = options.IsExport;
IsStatic = options.IsStatic;
JavaAccess = options.JavaAccess;
JavaNameOverride = options.JavaNameOverride;
JniSignature = options.RegisterSignature;
ManagedParameters = options.ManagedParameters;
Method = options.RegisterName + ":" + JniSignature + ":" + options.RegisterConnector;
Name = options.RegisterName;
ThrownTypeNames = options.ThrownTypeNames;

if (options.Style == JavaPeerStyle.XAJavaInterop1) {
Method = "n_" + Method;
}
ManagedParameters = managedParameters;
JniSignature = signature ?? throw new ArgumentNullException ("`connector` cannot be null.", nameof (connector));
Method = "n_" + name + ":" + JniSignature + ":" + connector;
Name = name;

var jnisig = JniSignature;
int closer = jnisig.IndexOf (')');
string ret = jnisig.Substring (closer + 1);
retval = JavaNativeTypeManager.Parse (ret)?.Type;
string jniparms = jnisig.Substring (1, closer - 1);
if (string.IsNullOrEmpty (jniparms) && string.IsNullOrEmpty (options.SuperCall))
if (string.IsNullOrEmpty (jniparms) && string.IsNullOrEmpty (superCall))
return;
var parms = new StringBuilder ();
var scall = new StringBuilder ();
var acall = new StringBuilder ();
bool first = true;
int i = 0;
foreach (JniTypeName jti in JavaNativeTypeManager.FromSignature (jniparms)) {
if (options.OuterType != null) {
acall.Append (options.OuterType).Append (".this");
options.OuterType = null;
if (outerType != null) {
acall.Append (outerType).Append (".this");
outerType = null;
continue;
}
string? parmType = jti.Type;
Expand All @@ -1017,7 +927,7 @@ public Signature (SignatureOptions options)
++i;
}
this.parms = parms.ToString ();
this.call = options.SuperCall != null ? options.SuperCall : scall.ToString ();
this.call = superCall != null ? superCall : scall.ToString ();
this.ActivateCall = acall.ToString ();
}

Expand Down Expand Up @@ -1154,21 +1064,13 @@ void GenerateMethod (Signature method, TextWriter sw)
sw.Write (' ');
if (method.IsStatic)
sw.Write ("static ");
if (CodeGenerationTarget == JavaPeerStyle.JavaInterop1) {
sw.Write ("native ");
}
sw.Write (method.Retval);
sw.Write (' ');
sw.Write (method.JavaName);
sw.Write (" (");
sw.Write (method.Params);
sw.Write (')');
sw.Write (method.ThrowsDeclaration);
if (CodeGenerationTarget == JavaPeerStyle.JavaInterop1) {
sw.WriteLine (";");
return;
}
sw.WriteLine ();
sw.WriteLine (method.ThrowsDeclaration);
sw.WriteLine ("\t{");
#if MONODROID_TIMING
sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}.{1}: time: \"+java.lang.System.currentTimeMillis());", name, method.Name);
Expand Down Expand Up @@ -1239,8 +1141,6 @@ StreamWriter OpenStream (string outputPath)
/// </summary>
public string GetDestinationPath (string outputPath)
{
Initialize ();

var dir = package.Replace ('.', Path.DirectorySeparatorChar);
return Path.Combine (outputPath, dir, name + ".java");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static void AddJniMethod (JniMethodMap toRegister, MethodInfo declaringMethod, M
if (signature == null || string.IsNullOrEmpty (signature.MemberName)) {
return;
}
toRegister [(signature.MemberName, signature.MemberSignature)] = targetMethod ?? declaringMethod;
toRegister [("n_" + signature.MemberName, signature.MemberSignature)] = targetMethod ?? declaringMethod;
}

static void AddClassMethods (JniMethodMap toRegister, Type type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public void AddExportMethods ()
.ToList ();
Assert.AreEqual (11, methods.Count);

Assert.AreEqual ("action", methods [0].Name);
Assert.AreEqual ("()V", methods [0].Signature);
Assert.AreEqual ("n_InstanceAction", methods [0].Name);
Assert.AreEqual ("()V", methods [0].Signature);

Assert.AreEqual ("staticAction", methods [1].Name);
Assert.AreEqual ("n_StaticAction", methods [1].Name);
Assert.AreEqual ("()V", methods [1].Signature);

#if NET
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy