-
Notifications
You must be signed in to change notification settings - Fork 59
[jnimarshalmethod-gen] Create delegate types for marshaling methods with 15+ parameters #711
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
Changes from all commits
775c4bf
50bb710
a456276
c42aa91
8f101c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,6 +159,66 @@ public static bool StaticFuncThisMethodTakesLotsOfParameters ( | |
return false; | ||
return true; | ||
} | ||
|
||
[JavaCallable ("staticManyParametersWithAutogeneratedDelegateType", Signature="(ZBCSIJFDLjava/lang/Object;Ljava/lang/String;Ljava/util/ArrayList;Ljava/lang/String;Ljava/lang/Object;DFJII)I")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand how this method differs from the existing "lots of parameters" test: How does this (pair of) method(s) differ from the current |
||
public static int staticManyParametersWithAutogeneratedDelegateType ( | ||
bool a, | ||
sbyte b, | ||
char c, | ||
short d, | ||
int e, | ||
long f, | ||
float g, | ||
double h, | ||
IntPtr i, // java.lang.Object | ||
IntPtr j, // java.lang.String | ||
IntPtr k, // java.util.ArrayList<String> | ||
IntPtr l, // java.lang.String | ||
IntPtr m, // java.lang.Object | ||
double n, | ||
float o, | ||
long p, | ||
int q, | ||
int rv) | ||
{ | ||
if (a != false) | ||
return -1; | ||
if (b != (byte) 0xb) | ||
return -1; | ||
if (c != 'c') | ||
return -1; | ||
if (d != (short) 0xd) | ||
return -1; | ||
if (e != 0xe) | ||
return -1; | ||
if (f != 0xf) | ||
return -1; | ||
if (g != 1.0f) | ||
return -1; | ||
if (h != 2.0) | ||
return -1; | ||
if (i == IntPtr.Zero) | ||
return -1; | ||
if (j == IntPtr.Zero) | ||
return -1; | ||
if (k == IntPtr.Zero) | ||
return -1; | ||
if (l == IntPtr.Zero) | ||
return -1; | ||
if (m == IntPtr.Zero) | ||
return -1; | ||
if (n != 3.0) | ||
return -1; | ||
if (o != 4.0f) | ||
return -1; | ||
if (p != 0x70) | ||
return -1; | ||
if (q != 111111) | ||
return -1; | ||
if (rv != 222222) | ||
return -1; | ||
return rv; | ||
} | ||
} | ||
|
||
[JniValueMarshaler (typeof (MyColorValueMarshaler))] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
|
@@ -12,6 +13,7 @@ | |
using Mono.Options; | ||
using Mono.Collections.Generic; | ||
using Java.Interop.Tools.Cecil; | ||
using System.Text; | ||
|
||
#if _DUMP_REGISTER_NATIVE_MEMBERS | ||
using Mono.Linq.Expressions; | ||
|
@@ -290,6 +292,7 @@ void CreateMarshalMethodAssembly (string path) | |
var destDir = string.IsNullOrEmpty (outDirectory) ? Path.GetDirectoryName (path) : outDirectory; | ||
var builder = CreateExportedMemberBuilder (); | ||
var matchType = typeNameRegexes.Count > 0; | ||
var newDelegates = new List<Type> (); | ||
|
||
if (Verbose) | ||
ColorWriteLine ($"Preparing marshal method assembly '{assemblyName}'", ConsoleColor.Cyan); | ||
|
@@ -419,7 +422,7 @@ void CreateMarshalMethodAssembly (string path) | |
if (signature == null) | ||
signature = builder.GetJniMethodSignature (method); | ||
|
||
registrationElements.Add (CreateRegistration (name, signature, lambda, targetType, methodName)); | ||
registrationElements.Add (CreateRegistration (name, signature, lambda, targetType, methodName, dm, newDelegates)); | ||
|
||
addedMethods.Add (methodName); | ||
} | ||
|
@@ -441,7 +444,7 @@ void CreateMarshalMethodAssembly (string path) | |
if (!string.IsNullOrEmpty (outDirectory)) | ||
path = Path.Combine (outDirectory, Path.GetFileName (path)); | ||
|
||
var mover = new TypeMover (dstAssembly, ad, path, definedTypes, resolver, cache); | ||
var mover = new TypeMover (dstAssembly, ad, path, newDelegates, definedTypes, resolver, cache); | ||
mover.Move (); | ||
|
||
if (!keepTemporary) | ||
|
@@ -465,17 +468,70 @@ void CreateMarshalMethodAssembly (string path) | |
typeof (string), | ||
}); | ||
|
||
static Expression CreateRegistration (string method, string signature, LambdaExpression lambda, ParameterExpression targetType, string methodName) | ||
static void CreateDelegateRuntimeManagedMethod (TypeBuilder tb, string name, Type returnType, Type[] parameterTypes) | ||
{ | ||
var mb = tb.DefineMethod (name, | ||
System.Reflection.MethodAttributes.Public | | ||
System.Reflection.MethodAttributes.HideBySig | | ||
System.Reflection.MethodAttributes.NewSlot | | ||
System.Reflection.MethodAttributes.Virtual, | ||
CallingConventions.Standard, returnType, parameterTypes); | ||
mb.SetImplementationFlags (System.Reflection.MethodImplAttributes.Runtime | System.Reflection.MethodImplAttributes.Managed); | ||
} | ||
|
||
static Expression CreateRegistration (string method, string signature, LambdaExpression lambda, ParameterExpression targetType, string methodName, ModuleBuilder dm, List<Type> createdDelegateList) | ||
{ | ||
Expression registrationDelegateType = null; | ||
if (lambda.Type.Assembly == typeof (object).Assembly || | ||
lambda.Type.Assembly == typeof (System.Linq.Enumerable).Assembly) { | ||
registrationDelegateType = Expression.Constant (lambda.Type, typeof (Type)); | ||
} | ||
else { | ||
string delegateTypeName; | ||
if (lambda.Type.Assembly.IsDynamic) { | ||
var typeNameBuilder = new StringBuilder ("__<$>_jni_marshal_"); | ||
var parameterTypes = new List<Type> (); | ||
foreach (var p in lambda.Parameters) { | ||
parameterTypes.Add (p.Type); | ||
} | ||
|
||
MarshalMemberBuilder.AddMarshalerTypeNameSuffix (typeNameBuilder, lambda.ReturnType, parameterTypes); | ||
|
||
var typeName = typeNameBuilder.ToString (); | ||
var existingType = dm.GetType (typeName); | ||
if (existingType == null) { | ||
var dtb = dm.DefineType (typeName, | ||
System.Reflection.TypeAttributes.AnsiClass | | ||
System.Reflection.TypeAttributes.Sealed, | ||
typeof (MulticastDelegate)); | ||
|
||
var dc = dtb.DefineConstructor ( | ||
System.Reflection.MethodAttributes.Public | | ||
System.Reflection.MethodAttributes.HideBySig | | ||
System.Reflection.MethodAttributes.RTSpecialName | | ||
System.Reflection.MethodAttributes.SpecialName, | ||
CallingConventions.Standard, new Type [] { typeof (object), typeof (IntPtr) }); | ||
dc.SetImplementationFlags (System.Reflection.MethodImplAttributes.Runtime | System.Reflection.MethodImplAttributes.Managed); | ||
|
||
CreateDelegateRuntimeManagedMethod (dtb, "Invoke", typeof (bool), parameterTypes.ToArray ()); | ||
|
||
parameterTypes.Add (typeof (AsyncCallback)); | ||
parameterTypes.Add (typeof (object)); | ||
|
||
CreateDelegateRuntimeManagedMethod (dtb, "BeginInvoke", typeof (IAsyncResult), parameterTypes.ToArray ()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to declare |
||
CreateDelegateRuntimeManagedMethod (dtb, "EndInvoke", typeof (bool), new Type [] { typeof (IAsyncResult) }); | ||
|
||
existingType = dtb.CreateType (); | ||
createdDelegateList.Add (existingType); | ||
} | ||
|
||
delegateTypeName = existingType.FullName; | ||
} else | ||
delegateTypeName = lambda.Type.FullName; | ||
|
||
Func<string, bool, Type> getType = Type.GetType; | ||
registrationDelegateType = Expression.Call (getType.GetMethodInfo (), | ||
Expression.Constant (lambda.Type.FullName, typeof (string)), | ||
Expression.Constant (delegateTypeName, typeof (string)), | ||
Expression.Constant (true, typeof (bool))); | ||
registrationDelegateType = Expression.Convert (registrationDelegateType, typeof (Type)); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…I ask because I'm wondering if there's some way to not add this
public
export, or at least find a "more suitable" location for it?