Skip to content

Commit

Permalink
[jnimarshalmethod-gen] Add jnimarshalmethod-gen.exe.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jonpryor committed Jan 14, 2015
1 parent 20eadd7 commit 176240d
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Java.Interop.sln
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linq.Expressions", "li
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop-PerformanceTests", "tests\Java.Interop-PerformanceTests\Java.Interop-PerformanceTests.csproj", "{6970466B-F6D1-417A-8A27-4FED8555EBD0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools.JniMarshalMethodGenerator", "tools\jnimarshalmethod-gen\Xamarin.Android.Tools.JniMarshalMethodGenerator.csproj", "{D1295A8F-4F42-461D-A046-564476C10002}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{D5A93398-AEB1-49F3-89DC-3904A47DB0C7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hello", "samples\Hello\Hello.csproj", "{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}"
Expand Down Expand Up @@ -75,6 +77,10 @@ Global
{B501D075-6183-4E1D-92C9-F7B5002475B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B501D075-6183-4E1D-92C9-F7B5002475B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B501D075-6183-4E1D-92C9-F7B5002475B1}.Release|Any CPU.Build.0 = Release|Any CPU
{D1295A8F-4F42-461D-A046-564476C10002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1295A8F-4F42-461D-A046-564476C10002}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1295A8F-4F42-461D-A046-564476C10002}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1295A8F-4F42-461D-A046-564476C10002}.Release|Any CPU.Build.0 = Release|Any CPU
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -99,6 +105,7 @@ Global
{B501D075-6183-4E1D-92C9-F7B5002475B1} = {4C173212-371D-45D8-BA83-9226194F48DC}
{5887B410-D448-4257-A46B-EAC03C80BE93} = {4C173212-371D-45D8-BA83-9226194F48DC}
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A} = {C8F58966-94BF-407F-914A-8654F8B8AE3B}
{D1295A8F-4F42-461D-A046-564476C10002} = {C8F58966-94BF-407F-914A-8654F8B8AE3B}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = tools\jnienv-gen\jnienv-gen.csproj
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ run-tests: $(TESTS)

run-ptests: $(PTESTS)
$(foreach t,$(PTESTS), $(call RUN_TEST,$(t)))

run-test-jnimarshal: bin/$(CONFIGURATION)/Java.Interop.Export-Tests.dll
MONO_TRACE_LISTENER=Console.Out \
mono --debug bin/$(CONFIGURATION)/jnimarshalmethod-gen.exe bin/$(CONFIGURATION)/Java.Interop.Export-Tests.dll
89 changes: 89 additions & 0 deletions tools/jnimarshalmethod-gen/App.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

using Java.Interop;

namespace Xamarin.Android.Tools.JniMarshalMethodGenerator {

class App {

internal const string Name = "jnimarshalmethod-gen";

public static void Main (string[] args)
{
var jvm = CreateJavaVM ();

foreach (var path in args) {
if (!File.Exists (path)) {
Console.Error.WriteLine ("{0}: Path '{1}' does not exist.", Name, path);
continue;
}
try {
CreateMarshalMethodAssembly (path);
}
catch (Exception e) {
Console.Error.WriteLine ("{0}: {1}", Name, e.Message);
Console.WriteLine (e);
Environment.ExitCode = 1;
}
}

jvm.Dispose ();
}

static JavaVM CreateJavaVM ()
{
var builder = new JreVMBuilder ();
return builder.CreateJreVM ();
}

static ExportedMemberBuilder CreateExportedMemberBuilder ()
{
return new ExportedMemberBuilder (JniEnvironment.Current.JavaVM);
}

static void CreateMarshalMethodAssembly (string path)
{
var assembly = Assembly.LoadFile (path);

var baseName = Path.GetFileNameWithoutExtension (path);
var assemblyName = new AssemblyName (baseName + "-JniMarshalMethods");
var destPath = assemblyName.Name + ".dll";
var builder = CreateExportedMemberBuilder ();

var da = AppDomain.CurrentDomain.DefineDynamicAssembly (
assemblyName,
AssemblyBuilderAccess.Save,
Path.GetDirectoryName (path));

var dm = da.DefineDynamicModule ("<default>", destPath);

foreach (var type in assembly.DefinedTypes) {
TypeBuilder dt = null;

var flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static;
foreach (var method in type.GetMethods (flags )) {
// TODO: Constructors, [Register] methods
var export = method.GetCustomAttribute<ExportAttribute> ();
if (export == null)
continue;
if (dt == null)
dt = dm.DefineType (type.FullName, TypeAttributes.Public | TypeAttributes.Sealed);

var mb = dt.DefineMethod (
method.Name,
MethodAttributes.Public | MethodAttributes.Static);
var lambda = builder.CreateMarshalFromJniMethodExpression (export, type, method);
lambda.CompileToMethod (mb);
}
if (dt != null)
dt.CreateType ();
}
da.Save (destPath);
}
}
}
27 changes: 27 additions & 0 deletions tools/jnimarshalmethod-gen/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Reflection;
using System.Runtime.CompilerServices;

// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.

[assembly: AssemblyTitle ("jnimarshalmethod-gen")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("Xamarin Inc.")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("Xamarin Inc.")]
[assembly: AssemblyTrademark ("Xamarin")]
[assembly: AssemblyCulture ("")]

// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.

[assembly: AssemblyVersion ("1.0.*")]

// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D1295A8F-4F42-461D-A046-564476C10002}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Xamarin.Android.Tools.JniMarshalMethodGenerator</RootNamespace>
<AssemblyName>jnimarshalmethod-gen</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="App.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\..\src\Java.Interop.Export\Java.Interop.Export.csproj">
<Project>{B501D075-6183-4E1D-92C9-F7B5002475B1}</Project>
<Name>Java.Interop.Export</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Java.Interop\Java.Interop.csproj">
<Project>{94BD81F7-B06F-4295-9636-F8A3B6BDC762}</Project>
<Name>Java.Interop</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj">
<Project>{5887B410-D448-4257-A46B-EAC03C80BE93}</Project>
<Name>Java.Runtime.Environment</Name>
</ProjectReference>
</ItemGroup>
</Project>

0 comments on commit 176240d

Please sign in to comment.