Skip to content

Commit 176240d

Browse files
committed
[jnimarshalmethod-gen] Add jnimarshalmethod-gen.exe.
jnimarshalmethod-gen.exe is a utility to generate all of the JNI Marshal Methods needed to support Java invoking [Export]ed methods. It was alluded to in commit 06cfd83: > Instead, long-term it would be "interesting" if we could use > ExportedMemberBuilder to process assemblies, generate the JNI method > marshaling code for ~everything, store that into a NEW assembly (as > part of the build process), and AOT the marshaling assembly! jnimarshalmethod-gen.exe is the *beginning* of that process: it only handles [Export]ed methods right now, and not [Register]d methods, and there's no facililty within Java.Interop to actually use this generated assembly (all TODOs!), but that said... jnimarshalmethod-gen.exe ASSEMBLY.dll will generate the file ASSEMBLY-JniMarshalMethods.dll which contains all of the JNI marshal methods that could (should) be registered with JNIEnv::RegisterNatives() to support Java > managed invocations. TODO: * Generate marshal methods for constructors. Related: commit 8c83f64, and finishing Java activation. * Generate marshal methods for overridden [Register]ed methods. Note: this needs to be aware of the inheritance hierarchy, and only emit marshal methods for methods overridden by managed code, NOT Java method overrides. * Fixup/improve JniType.RegisterNativeMethods() so that it will check for the *-JniMarshalMethods.dll assemblies and use any methods there. * Plausible variation: have the *-JniMarshalMethods.dll type contain a per-type "registration method" which calls JNIEnv::RegisterNatives()? The "glue logic" needs thinking.
1 parent 20eadd7 commit 176240d

File tree

5 files changed

+181
-0
lines changed

5 files changed

+181
-0
lines changed

Java.Interop.sln

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linq.Expressions", "li
2323
EndProject
2424
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop-PerformanceTests", "tests\Java.Interop-PerformanceTests\Java.Interop-PerformanceTests.csproj", "{6970466B-F6D1-417A-8A27-4FED8555EBD0}"
2525
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools.JniMarshalMethodGenerator", "tools\jnimarshalmethod-gen\Xamarin.Android.Tools.JniMarshalMethodGenerator.csproj", "{D1295A8F-4F42-461D-A046-564476C10002}"
27+
EndProject
2628
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{D5A93398-AEB1-49F3-89DC-3904A47DB0C7}"
2729
EndProject
2830
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hello", "samples\Hello\Hello.csproj", "{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}"
@@ -75,6 +77,10 @@ Global
7577
{B501D075-6183-4E1D-92C9-F7B5002475B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
7678
{B501D075-6183-4E1D-92C9-F7B5002475B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
7779
{B501D075-6183-4E1D-92C9-F7B5002475B1}.Release|Any CPU.Build.0 = Release|Any CPU
80+
{D1295A8F-4F42-461D-A046-564476C10002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
81+
{D1295A8F-4F42-461D-A046-564476C10002}.Debug|Any CPU.Build.0 = Debug|Any CPU
82+
{D1295A8F-4F42-461D-A046-564476C10002}.Release|Any CPU.ActiveCfg = Release|Any CPU
83+
{D1295A8F-4F42-461D-A046-564476C10002}.Release|Any CPU.Build.0 = Release|Any CPU
7884
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7985
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
8086
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -99,6 +105,7 @@ Global
99105
{B501D075-6183-4E1D-92C9-F7B5002475B1} = {4C173212-371D-45D8-BA83-9226194F48DC}
100106
{5887B410-D448-4257-A46B-EAC03C80BE93} = {4C173212-371D-45D8-BA83-9226194F48DC}
101107
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A} = {C8F58966-94BF-407F-914A-8654F8B8AE3B}
108+
{D1295A8F-4F42-461D-A046-564476C10002} = {C8F58966-94BF-407F-914A-8654F8B8AE3B}
102109
EndGlobalSection
103110
GlobalSection(MonoDevelopProperties) = preSolution
104111
StartupItem = tools\jnienv-gen\jnienv-gen.csproj

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@ run-tests: $(TESTS)
6161

6262
run-ptests: $(PTESTS)
6363
$(foreach t,$(PTESTS), $(call RUN_TEST,$(t)))
64+
65+
run-test-jnimarshal: bin/$(CONFIGURATION)/Java.Interop.Export-Tests.dll
66+
MONO_TRACE_LISTENER=Console.Out \
67+
mono --debug bin/$(CONFIGURATION)/jnimarshalmethod-gen.exe bin/$(CONFIGURATION)/Java.Interop.Export-Tests.dll

tools/jnimarshalmethod-gen/App.cs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq.Expressions;
4+
using System.Reflection;
5+
using System.Reflection.Emit;
6+
7+
using Java.Interop;
8+
9+
namespace Xamarin.Android.Tools.JniMarshalMethodGenerator {
10+
11+
class App {
12+
13+
internal const string Name = "jnimarshalmethod-gen";
14+
15+
public static void Main (string[] args)
16+
{
17+
var jvm = CreateJavaVM ();
18+
19+
foreach (var path in args) {
20+
if (!File.Exists (path)) {
21+
Console.Error.WriteLine ("{0}: Path '{1}' does not exist.", Name, path);
22+
continue;
23+
}
24+
try {
25+
CreateMarshalMethodAssembly (path);
26+
}
27+
catch (Exception e) {
28+
Console.Error.WriteLine ("{0}: {1}", Name, e.Message);
29+
Console.WriteLine (e);
30+
Environment.ExitCode = 1;
31+
}
32+
}
33+
34+
jvm.Dispose ();
35+
}
36+
37+
static JavaVM CreateJavaVM ()
38+
{
39+
var builder = new JreVMBuilder ();
40+
return builder.CreateJreVM ();
41+
}
42+
43+
static ExportedMemberBuilder CreateExportedMemberBuilder ()
44+
{
45+
return new ExportedMemberBuilder (JniEnvironment.Current.JavaVM);
46+
}
47+
48+
static void CreateMarshalMethodAssembly (string path)
49+
{
50+
var assembly = Assembly.LoadFile (path);
51+
52+
var baseName = Path.GetFileNameWithoutExtension (path);
53+
var assemblyName = new AssemblyName (baseName + "-JniMarshalMethods");
54+
var destPath = assemblyName.Name + ".dll";
55+
var builder = CreateExportedMemberBuilder ();
56+
57+
var da = AppDomain.CurrentDomain.DefineDynamicAssembly (
58+
assemblyName,
59+
AssemblyBuilderAccess.Save,
60+
Path.GetDirectoryName (path));
61+
62+
var dm = da.DefineDynamicModule ("<default>", destPath);
63+
64+
foreach (var type in assembly.DefinedTypes) {
65+
TypeBuilder dt = null;
66+
67+
var flags = BindingFlags.Public | BindingFlags.NonPublic |
68+
BindingFlags.Instance | BindingFlags.Static;
69+
foreach (var method in type.GetMethods (flags )) {
70+
// TODO: Constructors, [Register] methods
71+
var export = method.GetCustomAttribute<ExportAttribute> ();
72+
if (export == null)
73+
continue;
74+
if (dt == null)
75+
dt = dm.DefineType (type.FullName, TypeAttributes.Public | TypeAttributes.Sealed);
76+
77+
var mb = dt.DefineMethod (
78+
method.Name,
79+
MethodAttributes.Public | MethodAttributes.Static);
80+
var lambda = builder.CreateMarshalFromJniMethodExpression (export, type, method);
81+
lambda.CompileToMethod (mb);
82+
}
83+
if (dt != null)
84+
dt.CreateType ();
85+
}
86+
da.Save (destPath);
87+
}
88+
}
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
4+
// Information about this assembly is defined by the following attributes.
5+
// Change them to the values specific to your project.
6+
7+
[assembly: AssemblyTitle ("jnimarshalmethod-gen")]
8+
[assembly: AssemblyDescription ("")]
9+
[assembly: AssemblyConfiguration ("")]
10+
[assembly: AssemblyCompany ("Xamarin Inc.")]
11+
[assembly: AssemblyProduct ("")]
12+
[assembly: AssemblyCopyright ("Xamarin Inc.")]
13+
[assembly: AssemblyTrademark ("Xamarin")]
14+
[assembly: AssemblyCulture ("")]
15+
16+
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17+
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
18+
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
19+
20+
[assembly: AssemblyVersion ("1.0.*")]
21+
22+
// The following attributes are used to specify the signing key for the assembly,
23+
// if desired. See the Mono documentation for more information about signing.
24+
25+
//[assembly: AssemblyDelaySign(false)]
26+
//[assembly: AssemblyKeyFile("")]
27+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6+
<ProductVersion>8.0.30703</ProductVersion>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{D1295A8F-4F42-461D-A046-564476C10002}</ProjectGuid>
9+
<OutputType>Exe</OutputType>
10+
<RootNamespace>Xamarin.Android.Tools.JniMarshalMethodGenerator</RootNamespace>
11+
<AssemblyName>jnimarshalmethod-gen</AssemblyName>
12+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13+
</PropertyGroup>
14+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
15+
<DebugSymbols>true</DebugSymbols>
16+
<DebugType>full</DebugType>
17+
<Optimize>false</Optimize>
18+
<OutputPath>..\..\bin\Debug</OutputPath>
19+
<DefineConstants>DEBUG;</DefineConstants>
20+
<ErrorReport>prompt</ErrorReport>
21+
<WarningLevel>4</WarningLevel>
22+
<Externalconsole>true</Externalconsole>
23+
</PropertyGroup>
24+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25+
<DebugType>full</DebugType>
26+
<Optimize>true</Optimize>
27+
<OutputPath>..\..\bin\Release</OutputPath>
28+
<ErrorReport>prompt</ErrorReport>
29+
<WarningLevel>4</WarningLevel>
30+
<Externalconsole>true</Externalconsole>
31+
</PropertyGroup>
32+
<ItemGroup>
33+
<Reference Include="System" />
34+
</ItemGroup>
35+
<ItemGroup>
36+
<Compile Include="Properties\AssemblyInfo.cs" />
37+
<Compile Include="App.cs" />
38+
</ItemGroup>
39+
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
40+
<ItemGroup>
41+
<ProjectReference Include="..\..\src\Java.Interop.Export\Java.Interop.Export.csproj">
42+
<Project>{B501D075-6183-4E1D-92C9-F7B5002475B1}</Project>
43+
<Name>Java.Interop.Export</Name>
44+
</ProjectReference>
45+
<ProjectReference Include="..\..\src\Java.Interop\Java.Interop.csproj">
46+
<Project>{94BD81F7-B06F-4295-9636-F8A3B6BDC762}</Project>
47+
<Name>Java.Interop</Name>
48+
</ProjectReference>
49+
<ProjectReference Include="..\..\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj">
50+
<Project>{5887B410-D448-4257-A46B-EAC03C80BE93}</Project>
51+
<Name>Java.Runtime.Environment</Name>
52+
</ProjectReference>
53+
</ItemGroup>
54+
</Project>

0 commit comments

Comments
 (0)