Skip to content

Commit 06985ed

Browse files
committed
Generate general delegate types for marshaling delegates
1 parent afbc5b3 commit 06985ed

File tree

2 files changed

+67
-14
lines changed

2 files changed

+67
-14
lines changed

src/Java.Interop.Export/Java.Interop/MarshalMemberBuilder.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,23 +254,22 @@ static Type GetMarshalerType (Type returnType, List<Type> funcTypeParams, Type d
254254
funcTypeParams.RemoveRange (0, 2);
255255
var marshalDelegateName = new StringBuilder ();
256256
marshalDelegateName.Append ("_JniMarshal_PP");
257-
foreach (var paramType in funcTypeParams) {
258-
marshalDelegateName.Append (GetJniMarshalDelegateParameterIdentifier (paramType));
259-
}
260-
marshalDelegateName.Append ("_");
261-
if (returnType == null) {
262-
marshalDelegateName.Append ("V");
263-
} else {
264-
marshalDelegateName.Append (GetJniMarshalDelegateParameterIdentifier (returnType));
265-
}
257+
AddMarshalerTypeNameSuffix (marshalDelegateName, returnType, funcTypeParams);
266258

267259
Type marshalDelegateType = declaringType.Assembly.GetType (marshalDelegateName.ToString (), throwOnError: false);
268260

269-
// Punt?; System.Linq.Expressions will automagically produce the needed delegate type.
270-
// Unfortunately, this won't work with jnimarshalmethod-gen.exe.
271261
return marshalDelegateType;
272262
}
273263

264+
public static void AddMarshalerTypeNameSuffix (StringBuilder sb, Type returnType, List<Type> funcTypeParams)
265+
{
266+
foreach (var paramType in funcTypeParams)
267+
sb.Append (GetJniMarshalDelegateParameterIdentifier (paramType));
268+
269+
sb.Append ("_");
270+
sb.Append (returnType == null ? 'V' : GetJniMarshalDelegateParameterIdentifier (returnType));
271+
}
272+
274273
static char GetJniMarshalDelegateParameterIdentifier (Type type)
275274
{
276275
if (type == typeof (bool)) return 'Z';

tools/jnimarshalmethod-gen/App.cs

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Linq;
45
using System.Linq.Expressions;
56
using System.Reflection;
67
using System.Reflection.Emit;
@@ -12,6 +13,7 @@
1213
using Mono.Options;
1314
using Mono.Collections.Generic;
1415
using Java.Interop.Tools.Cecil;
16+
using System.Text;
1517

1618
#if _DUMP_REGISTER_NATIVE_MEMBERS
1719
using Mono.Linq.Expressions;
@@ -423,7 +425,7 @@ void CreateMarshalMethodAssembly (string path)
423425
if (signature == null)
424426
signature = builder.GetJniMethodSignature (method);
425427

426-
registrationElements.Add (CreateRegistration (name, signature, lambda, targetType, methodName));
428+
registrationElements.Add (CreateRegistration (name, signature, lambda, targetType, methodName, dm));
427429

428430
addedMethods.Add (methodName);
429431
}
@@ -469,17 +471,69 @@ void CreateMarshalMethodAssembly (string path)
469471
typeof (string),
470472
});
471473

472-
static Expression CreateRegistration (string method, string signature, LambdaExpression lambda, ParameterExpression targetType, string methodName)
474+
static void CreateDelegateRuntimeManagedMethod (TypeBuilder tb, string name, Type returnType, Type[] parameterTypes)
475+
{
476+
var mb = tb.DefineMethod (name,
477+
System.Reflection.MethodAttributes.Public |
478+
System.Reflection.MethodAttributes.HideBySig |
479+
System.Reflection.MethodAttributes.NewSlot |
480+
System.Reflection.MethodAttributes.Virtual,
481+
CallingConventions.Standard, returnType, parameterTypes);
482+
mb.SetImplementationFlags (System.Reflection.MethodImplAttributes.Runtime | System.Reflection.MethodImplAttributes.Managed);
483+
}
484+
485+
static Expression CreateRegistration (string method, string signature, LambdaExpression lambda, ParameterExpression targetType, string methodName, ModuleBuilder dm)
473486
{
474487
Expression registrationDelegateType = null;
475488
if (lambda.Type.Assembly == typeof (object).Assembly ||
476489
lambda.Type.Assembly == typeof (System.Linq.Enumerable).Assembly) {
477490
registrationDelegateType = Expression.Constant (lambda.Type, typeof (Type));
478491
}
479492
else {
493+
string delegateTypeName;
494+
if (lambda.Type.Assembly.IsDynamic) {
495+
var typeNameBuilder = new StringBuilder ("__<$>_jni_marshal_");
496+
var parameterTypes = new List<Type> ();
497+
foreach (var p in lambda.Parameters) {
498+
parameterTypes.Add (p.Type);
499+
}
500+
501+
MarshalMemberBuilder.AddMarshalerTypeNameSuffix (typeNameBuilder, lambda.ReturnType, parameterTypes);
502+
503+
var typeName = typeNameBuilder.ToString ();
504+
var existingType = dm.GetType (typeName);
505+
if (existingType == null) {
506+
var dtb = dm.DefineType (typeName,
507+
System.Reflection.TypeAttributes.AnsiClass |
508+
System.Reflection.TypeAttributes.Sealed,
509+
typeof (MulticastDelegate));
510+
511+
var dc = dtb.DefineConstructor (
512+
System.Reflection.MethodAttributes.Public |
513+
System.Reflection.MethodAttributes.HideBySig |
514+
System.Reflection.MethodAttributes.RTSpecialName |
515+
System.Reflection.MethodAttributes.SpecialName,
516+
CallingConventions.Standard, new Type [] { typeof (object), typeof (IntPtr) });
517+
dc.SetImplementationFlags (System.Reflection.MethodImplAttributes.Runtime | System.Reflection.MethodImplAttributes.Managed);
518+
519+
CreateDelegateRuntimeManagedMethod (dtb, "Invoke", null, parameterTypes.ToArray ());
520+
521+
parameterTypes.Add (typeof (AsyncCallback));
522+
parameterTypes.Add (typeof (object));
523+
524+
CreateDelegateRuntimeManagedMethod (dtb, "BeginInvoke", typeof (IAsyncResult), parameterTypes.ToArray ());
525+
CreateDelegateRuntimeManagedMethod (dtb, "EndInvoke", typeof (bool), new Type [] { typeof (IAsyncResult) });
526+
527+
existingType = dtb.CreateType ();
528+
}
529+
530+
delegateTypeName = existingType.FullName;
531+
} else
532+
delegateTypeName = lambda.Type.FullName;
533+
480534
Func<string, bool, Type> getType = Type.GetType;
481535
registrationDelegateType = Expression.Call (getType.GetMethodInfo (),
482-
Expression.Constant (lambda.Type.FullName, typeof (string)),
536+
Expression.Constant (delegateTypeName, typeof (string)),
483537
Expression.Constant (true, typeof (bool)));
484538
registrationDelegateType = Expression.Convert (registrationDelegateType, typeof (Type));
485539
}

0 commit comments

Comments
 (0)