Browse Source

Rewrite pinvoke marshalling to fix support for passing classes by ref/by value, and returning classes by value. Add support for inline methods. Fix some minor bugs.

pull/1/head
Zoltan Varga 15 years ago committed by Andreia Gaita
parent
commit
bbf5789cab
  1. 276
      src/Mono.VisualC.Interop/ABI/CppAbi.cs
  2. 96
      src/Mono.VisualC.Interop/ABI/Impl/ItaniumAbi.cs
  3. 3
      src/Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs
  4. 3
      src/Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs
  5. 3
      src/Mono.VisualC.Interop/CppTypeInfo.cs

276
src/Mono.VisualC.Interop/ABI/CppAbi.cs

@ -14,11 +14,38 @@ using System.Reflection.Emit; @@ -14,11 +14,38 @@ using System.Reflection.Emit;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Mono.VisualC.Interop.Util;
namespace Mono.VisualC.Interop.ABI {
//
// Marshalling to be done for a single parameter
//
public enum ParameterMarshal {
Default = 0,
ClassByRef = 1,
ClassByVal = 2
}
//
// Describes the signature of the pinvoke wrapper of a c++ method, along with
// marshalling information
//
public class PInvokeSignature {
// The original c# method this signature was generated from
public MethodInfo OrigMethod;
public List<Type> ParameterTypes { get; set; }
public List<ParameterMarshal> ParameterMarshallers { get; set; }
public Type ReturnType { get; set; }
// Whenever to return a class value
public bool ReturnClass { get; set; }
// Whenever to return a class value by passing a hidden first argument
// Used by the itanium c++ abi
public bool ReturnByAddr { get; set; }
}
//FIXME: Exception handling, operator overloading etc.
//FIXME: Allow interface to override default calling convention
public abstract partial class CppAbi {
@ -87,7 +114,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -87,7 +114,7 @@ namespace Mono.VisualC.Interop.ABI {
var properties = GetProperties ();
var methods = GetMethods ();
CppTypeInfo typeInfo = MakeTypeInfo (methods.Where (m => IsVirtual (m)));
CppTypeInfo typeInfo = MakeTypeInfo (methods, methods.Where (m => IsVirtual (m)));
// Implement all methods
int vtableIndex = 0;
@ -103,7 +130,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -103,7 +130,7 @@ namespace Mono.VisualC.Interop.ABI {
return (Iface)Activator.CreateInstance (impl_type.CreateType (), typeInfo);
}
protected virtual CppTypeInfo MakeTypeInfo (IEnumerable<MethodInfo> virtualMethods)
protected virtual CppTypeInfo MakeTypeInfo (IEnumerable<MethodInfo> methods, IEnumerable<MethodInfo> virtualMethods)
{
return new CppTypeInfo (this, virtualMethods, layout_type);
}
@ -197,6 +224,8 @@ namespace Mono.VisualC.Interop.ABI { @@ -197,6 +224,8 @@ namespace Mono.VisualC.Interop.ABI {
bool isStatic = IsStatic (interfaceMethod);
LocalBuilder cppInstancePtr = null;
LocalBuilder nativePtr = null;
LocalBuilder retVal = null;
LocalBuilder retArg = null;
// If we're an instance method, load up the "this" pointer
if (!isStatic)
@ -213,23 +242,75 @@ namespace Mono.VisualC.Interop.ABI { @@ -213,23 +242,75 @@ namespace Mono.VisualC.Interop.ABI {
MethodInfo nativeMethod;
var psig = GetPInvokeSignature (typeInfo, interfaceMethod);
if (psig.ReturnClass) {
Debug.Assert (wrapper_type != null);
retVal = il.DeclareLocal (wrapper_type);
// Construct the manager wrapper object
var ctor = wrapper_type.GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type [] { typeof (CppLibrary) }, null);
Debug.Assert (ctor != null);
il.Emit (OpCodes.Ldnull);
il.Emit (OpCodes.Newobj, ctor);
il.Emit (OpCodes.Stloc, retVal);
psig.ReturnType = layout_type;
}
if (psig.ReturnByAddr) {
//
// When using the Itanium c++ abi, some classes are returned by passing a
// hidden first argument.
//
// Put the address of the native return memory into a local
retArg = il.DeclareLocal (typeof (IntPtr));
il.Emit (OpCodes.Ldloc, retVal);
EmitLoadNativePtr (il);
il.Emit (OpCodes.Stloc, retArg);
psig.ReturnType = typeof (void);
}
if (IsVirtual (interfaceMethod) && methodType != MethodType.NativeDtor)
nativeMethod = EmitPrepareVirtualCall (il, typeInfo, nativePtr, vtableIndex++);
else
nativeMethod = GetPInvokeForMethod (interfaceMethod);
nativeMethod = GetPInvokeForMethod (interfaceMethod, psig);
switch (methodType) {
case MethodType.NativeCtor:
EmitConstruct (il, nativeMethod, parameterTypes, nativePtr);
EmitConstruct (il, nativeMethod, psig, nativePtr);
break;
case MethodType.NativeDtor:
EmitDestruct (il, nativeMethod, parameterTypes, cppInstancePtr, nativePtr);
EmitDestruct (il, nativeMethod, psig, cppInstancePtr, nativePtr);
break;
default:
EmitCallNative (il, nativeMethod, isStatic, parameterTypes, nativePtr);
EmitNativeCall (il, nativeMethod, isStatic, psig, nativePtr, retArg);
break;
}
if (psig.ReturnClass) {
if (!psig.ReturnByAddr) {
//
// The method return a struct in native format which is on the stack,
// have to copy into the native memory belonging to our object
//
// Save the method return value
var rval = il.DeclareLocal (layout_type);
il.Emit (OpCodes.Stloc, rval);
// Load the ptr to the native memory (dest)
il.Emit (OpCodes.Ldloc, retVal);
EmitLoadNativePtr (il);
// Load the address of the method return value (src)
il.Emit (OpCodes.Ldloca, rval);
// Copy
il.Emit (OpCodes.Cpobj, layout_type);
}
il.Emit (OpCodes.Ldloc, retVal);
}
il.Emit (OpCodes.Ret);
return trampoline;
}
@ -303,13 +384,13 @@ namespace Mono.VisualC.Interop.ABI { @@ -303,13 +384,13 @@ namespace Mono.VisualC.Interop.ABI {
if (targetMethod == null)
return null;
Type[] parameterTypes = GetParameterTypesForPInvoke (interfaceMethod).ToArray ();
var psig = GetPInvokeSignature (typeInfo, interfaceMethod);
// TODO: According to http://msdn.microsoft.com/en-us/library/w16z8yc4.aspx
// The dynamic method created with this constructor has access to public and internal members of all the types contained in module m.
// This does not appear to hold true, so we also disable JIT visibility checks.
DynamicMethod trampolineIn = new DynamicMethod (wrapper_type.Name + "_" + interfaceMethod.Name + "_FromNative", interfaceMethod.ReturnType,
parameterTypes, typeof (CppInstancePtr).Module, true);
DynamicMethod trampolineIn = new DynamicMethod (wrapper_type.Name + "_" + interfaceMethod.Name + "_FromNative", psig.ReturnType,
psig.ParameterTypes.ToArray (), typeof (CppInstancePtr).Module, true);
ReflectionHelper.ApplyMethodParameterAttributes (interfaceMethod, trampolineIn, true);
ILGenerator il = trampolineIn.GetILGenerator ();
@ -330,7 +411,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -330,7 +411,7 @@ namespace Mono.VisualC.Interop.ABI {
il.Emit (OpCodes.Call, getManagedObj);
}
for (int i = argLoadStart; i < parameterTypes.Length; i++) {
for (int i = argLoadStart; i < psig.ParameterTypes.Count; i++) {
il.Emit (OpCodes.Ldarg, i);
}
il.Emit (OpCodes.Tailcall);
@ -363,23 +444,28 @@ namespace Mono.VisualC.Interop.ABI { @@ -363,23 +444,28 @@ namespace Mono.VisualC.Interop.ABI {
MethodBuilder methodBuilder = impl_type.DefineMethod (interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual,
interfaceMethod.ReturnType, parameterTypes);
ReflectionHelper.ApplyMethodParameterAttributes (interfaceMethod, methodBuilder, false);
return methodBuilder;
}
/**
* Defines a new MethodBuilder that calls the specified C++ (non-virtual) method using its mangled name
*/
protected virtual MethodBuilder GetPInvokeForMethod (MethodInfo signature)
protected virtual MethodBuilder GetPInvokeForMethod (MethodInfo signature, PInvokeSignature psig)
{
string entryPoint = GetMangledMethodName (signature);
if (entryPoint == null)
throw new NotSupportedException ("Could not mangle method name.");
Type [] parameterTypes = GetParameterTypesForPInvoke (signature).ToArray ();
string lib;
if (IsInline (signature))
lib = library + "-inline";
else
lib = library;
MethodBuilder builder = impl_type.DefinePInvokeMethod ("__$" + signature.Name + "_Impl", library, entryPoint,
MethodBuilder builder = impl_type.DefinePInvokeMethod ("__$" + signature.Name + "_Impl", lib, entryPoint,
MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.PinvokeImpl,
CallingConventions.Standard, signature.ReturnType, parameterTypes,
CallingConventions.Standard, psig.ReturnType, psig.ParameterTypes.ToArray (),
GetCallingConvention (signature).Value, CharSet.Ansi);
builder.SetImplementationFlags (builder.GetMethodImplementationFlags () | MethodImplAttributes.PreserveSig);
ReflectionHelper.ApplyMethodParameterAttributes (signature, builder, true);
@ -419,24 +505,22 @@ namespace Mono.VisualC.Interop.ABI { @@ -419,24 +505,22 @@ namespace Mono.VisualC.Interop.ABI {
if (wrapper_type != null) {
// load managed wrapper
il.Emit (OpCodes.Ldarg_1);
il.Emit (OpCodes.Newobj, typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null,
new Type[] { typeof (int), typeof (object) }, null));
il.Emit (OpCodes.Newobj, typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (int), typeof (object) }, null));
} else
il.Emit (OpCodes.Newobj, typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null,
new Type[] { typeof (int) }, null));
il.Emit (OpCodes.Newobj, typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (int) }, null));
}
protected virtual void EmitConstruct (ILGenerator il, MethodInfo nativeMethod, Type [] parameterTypes,
protected virtual void EmitConstruct (ILGenerator il, MethodInfo nativeMethod,
PInvokeSignature psig,
LocalBuilder nativePtr)
{
EmitCallNative (il, nativeMethod, false, parameterTypes, nativePtr);
//
// FIXME: Why is this needed ? When using the itanium abi, the c++ ctor
// initalizes it. Maybe msvc needs it ?
EmitNativeCall (il, nativeMethod, false, psig, nativePtr, null);
// FIXME: Why is this needed ? The c++ ctor initializes it
//EmitInitVTable (il, nativePtr);
}
protected virtual void EmitDestruct (ILGenerator il, MethodInfo nativeMethod, Type [] parameterTypes,
protected virtual void EmitDestruct (ILGenerator il, MethodInfo nativeMethod,
PInvokeSignature psig,
LocalBuilder cppInstancePtr, LocalBuilder nativePtr)
{
// bail if we weren't alloc'd by managed code
@ -449,7 +533,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -449,7 +533,7 @@ namespace Mono.VisualC.Interop.ABI {
il.Emit (OpCodes.Brfalse_S, bail);
EmitResetVTable (il, nativePtr);
EmitCallNative (il, nativeMethod, false, parameterTypes, nativePtr);
EmitNativeCall (il, nativeMethod, false, psig, nativePtr, null);
il.MarkLabel (bail);
}
@ -459,43 +543,128 @@ namespace Mono.VisualC.Interop.ABI { @@ -459,43 +543,128 @@ namespace Mono.VisualC.Interop.ABI {
* GetPInvokeForMethod or the MethodInfo of a vtable method.
* To complete method, emit OpCodes.Ret.
*/
protected virtual void EmitCallNative (ILGenerator il, MethodInfo nativeMethod, bool isStatic, Type [] parameterTypes,
LocalBuilder nativePtr)
{
int argLoadStart = 1; // For static methods, just strip off arg0 (.net this pointer)
if (!isStatic)
protected virtual void EmitNativeCall (ILGenerator il, MethodInfo nativeMethod,
bool isStatic, PInvokeSignature psig,
LocalBuilder nativePtr, LocalBuilder retArg)
{
argLoadStart = 2; // For instance methods, strip off CppInstancePtr and pass the corresponding IntPtr
il.Emit (OpCodes.Ldloc_S, nativePtr);
}
for (int i = argLoadStart; i <= parameterTypes.Length; i++) {
il.Emit (OpCodes.Ldarg, i);
EmitSpecialParameterMarshal (il, parameterTypes [i - 1]);
}
//
// The managed signature looks like this:
// (<.net this>, @this (if not static), <additional args>
// The native signature looks like this:
// (<hidden retarg if present>, @this, <additional args>)
//
// The managed argument index, skip .net this
int aindex = 1;
il.Emit (OpCodes.Call, nativeMethod);
// Do conversions
LocalBuilder[] args = new LocalBuilder [psig.ParameterTypes.Count];
aindex = 1;
for (int pindex = 0; pindex < psig.ParameterTypes.Count; pindex++) {
if (!isStatic && pindex == 0) {
// For instance methods, strip off CppInstancePtr and pass the corresponding IntPtr
args [pindex] = nativePtr;
aindex ++;
continue;
}
// Note: when this is modified, usually GetParameterTypesForPInvoke types should be updated too
protected virtual void EmitSpecialParameterMarshal (ILGenerator il, Type parameterType)
{
Type ptype = psig.ParameterTypes [pindex];
switch (psig.ParameterMarshallers [pindex]) {
case ParameterMarshal.Default:
// FIXME: Why is this needed ?
// auto marshal bool to C++ bool type (0 = false , 1 = true )
if (parameterType.Equals (typeof (bool))) {
if (ptype.Equals (typeof (bool))) {
args [pindex] = il.DeclareLocal (typeof (bool));
Label isTrue = il.DefineLabel ();
Label done = il.DefineLabel ();
il.Emit (OpCodes.Ldarg, aindex);
il.Emit (OpCodes.Brtrue_S, isTrue);
il.Emit (OpCodes.Ldc_I4_0);
il.Emit (OpCodes.Br_S, done);
il.MarkLabel (isTrue);
il.Emit (OpCodes.Ldc_I4_1);
il.MarkLabel (done);
il.Emit (OpCodes.Stloc, args [pindex]);
//il.Emit (OpCodes.Conv_I1);
}
// auto marshal ICppObject
break;
case ParameterMarshal.ClassByRef: {
args [pindex] = il.DeclareLocal (typeof (IntPtr));
// Pass the native pointer of the class
// Null check
Label isNull = il.DefineLabel ();
Label contLabel = il.DefineLabel ();
il.Emit (OpCodes.Ldarg, aindex);
il.Emit (OpCodes.Brfalse_S, isNull);
// Non-null case
il.Emit (OpCodes.Ldarg, aindex);
EmitLoadNativePtr (il);
// FIXME: Dispose check
il.Emit (OpCodes.Br_S, contLabel);
// Null case
il.MarkLabel (isNull);
il.Emit (OpCodes.Ldnull);
il.Emit (OpCodes.Conv_I);
// Common case
il.MarkLabel (contLabel);
il.Emit (OpCodes.Stloc, args [pindex]);
break;
}
case ParameterMarshal.ClassByVal: {
// Pass a copy of the native memory of the class
args [pindex] = il.DeclareLocal (ptype);
Label normalLabel = il.DefineLabel ();
il.Emit (OpCodes.Ldarg, aindex);
il.Emit (OpCodes.Brtrue_S, normalLabel);
// Null case
il.Emit (OpCodes.Ldstr, "Cannot pass null object of type '" + ptype.DeclaringType + "' to c++ by value");
il.Emit (OpCodes.Newobj, typeof (ArgumentException).GetConstructor (new Type[] { typeof(string) }));
il.Emit (OpCodes.Throw);
// Non-null case
il.MarkLabel (normalLabel);
// Dest
il.Emit (OpCodes.Ldloca, args [pindex]);
// Load the native ptr of the object (src)
il.Emit (OpCodes.Ldarg, aindex);
EmitLoadNativePtr (il);
// FIXME: Dispose check
// Copy
il.Emit (OpCodes.Cpobj, ptype);
break;
}
default:
throw new NotImplementedException ();
}
public virtual IEnumerable<Type> GetParameterTypesForPInvoke (MethodInfo method)
{
aindex ++;
}
// Pass arguments
aindex = 1;
int pindexStart = 0;
if (retArg != null) {
pindexStart ++;
il.Emit (OpCodes.Ldloc, retArg);
}
for (int pindex = pindexStart; pindex < psig.ParameterTypes.Count; pindex++) {
// The first argument is the .net this argument
if (args [pindex] != null)
il.Emit (OpCodes.Ldloc, args [pindex]);
else
il.Emit (OpCodes.Ldarg, aindex);
aindex ++;
}
// Make the call
il.Emit (OpCodes.Call, nativeMethod);
}
public virtual PInvokeSignature GetPInvokeSignature (CppTypeInfo typeInfo, MethodInfo method) {
var originalTypes = ReflectionHelper.GetMethodParameterTypes (method);
var pinvokeTypes = originalTypes.Transform (
@ -506,7 +675,10 @@ namespace Mono.VisualC.Interop.ABI { @@ -506,7 +675,10 @@ namespace Mono.VisualC.Interop.ABI {
For.UnmatchedInput<Type> ().Emit (t => t)
);
return pinvokeTypes;
Type returnType = method.ReturnType;
return new PInvokeSignature { OrigMethod = method, ParameterTypes = pinvokeTypes.ToList (), ReturnType = returnType };
}
/**
@ -607,6 +779,17 @@ namespace Mono.VisualC.Interop.ABI { @@ -607,6 +779,17 @@ namespace Mono.VisualC.Interop.ABI {
throw new ArgumentException ("First argument to non-static C++ method must be byref, IntPtr or CppInstancePtr.");
}
// Emit obj.Native.Native
// On enter, the stack should contain a reference to a CppInstancePtr
// On exit, it contains an IntPtr
void EmitLoadNativePtr (ILGenerator il) {
LocalBuilder cppip = il.DeclareLocal (typeof (CppInstancePtr));
il.Emit (OpCodes.Call, typeof (ICppObject).GetMethod ("get_Native"));
il.Emit (OpCodes.Stloc_S, cppip);
il.Emit (OpCodes.Ldloca_S, cppip);
il.Emit (OpCodes.Call, typeof (CppInstancePtr).GetProperty ("Native").GetGetMethod ());
}
protected virtual void EmitCheckManagedAlloc (ILGenerator il, LocalBuilder cppip)
{
// make sure we were allocated by managed code
@ -639,5 +822,4 @@ namespace Mono.VisualC.Interop.ABI { @@ -639,5 +822,4 @@ namespace Mono.VisualC.Interop.ABI {
}
}
}
}

96
src/Mono.VisualC.Interop/ABI/Impl/ItaniumAbi.cs

@ -23,9 +23,19 @@ namespace Mono.VisualC.Interop.ABI { @@ -23,9 +23,19 @@ namespace Mono.VisualC.Interop.ABI {
{
}
protected override CppTypeInfo MakeTypeInfo (IEnumerable<MethodInfo> virtualMethods)
protected override CppTypeInfo MakeTypeInfo (IEnumerable<MethodInfo> methods, IEnumerable<MethodInfo> virtualMethods)
{
return new ItaniumTypeInfo (this, virtualMethods, layout_type);
bool hasExplicitCopyCtor = false;
bool hasExplicitDtor = false;
foreach (var m in methods) {
if (m.IsDefined (typeof (CopyConstructorAttribute), false) && !m.IsDefined (typeof (ArtificialAttribute), false))
hasExplicitCopyCtor = true;
if (m.IsDefined (typeof (DestructorAttribute), false) && !m.IsDefined (typeof (ArtificialAttribute), false))
hasExplicitDtor = true;
}
return new ItaniumTypeInfo (this, virtualMethods, layout_type) { HasExplicitCopyCtor = hasExplicitCopyCtor, HasExplicitDtor = hasExplicitDtor };
}
public override CallingConvention? GetCallingConvention (MethodInfo methodInfo)
@ -35,12 +45,17 @@ namespace Mono.VisualC.Interop.ABI { @@ -35,12 +45,17 @@ namespace Mono.VisualC.Interop.ABI {
protected override string GetMangledMethodName (MethodInfo methodInfo)
{
var compressMap = new Dictionary<string, int> ();
string methodName = methodInfo.Name;
MethodType methodType = GetMethodType (methodInfo);
ParameterInfo [] parameters = methodInfo.GetParameters ();
StringBuilder nm = new StringBuilder ("_ZN", 30);
nm.Append (class_name.Length).Append (class_name);
compressMap [class_name] = compressMap.Count;
// FIXME: Implement compression completely
switch (methodType) {
case MethodType.NativeCtor:
@ -63,12 +78,16 @@ namespace Mono.VisualC.Interop.ABI { @@ -63,12 +78,16 @@ namespace Mono.VisualC.Interop.ABI {
nm.Append ('v');
else
for (int i = argStart; i < parameters.Length; i++)
nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType)));
nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType), compressMap));
return nm.ToString ();
}
public virtual string GetTypeCode (CppType mangleType)
public virtual string GetTypeCode (CppType mangleType) {
return GetTypeCode (mangleType, new Dictionary<string, int> ());
}
string GetTypeCode (CppType mangleType, Dictionary<string, int> compressMap)
{
CppTypes element = mangleType.ElementType;
IEnumerable<CppModifiers> modifiers = mangleType.Modifiers;
@ -102,16 +121,81 @@ namespace Mono.VisualC.Interop.ABI { @@ -102,16 +121,81 @@ namespace Mono.VisualC.Interop.ABI {
case CppTypes.Class:
case CppTypes.Struct:
case CppTypes.Union:
case CppTypes.Enum:
case CppTypes.Enum: {
int cid;
if (compressMap.TryGetValue (mangleType.ElementTypeName, out cid)) {
if (cid == 0)
code.Append ("S_");
else
throw new NotImplementedException ();
} else {
code.Append(mangleType.ElementTypeName.Length);
code.Append(mangleType.ElementTypeName);
}
break;
}
}
return code.ToString ();
}
public override PInvokeSignature GetPInvokeSignature (CppTypeInfo typeInfo, MethodInfo method) {
Type returnType = method.ReturnType;
bool retClass = false;
bool retByAddr = false;
if (typeof (ICppObject).IsAssignableFrom (returnType)) {
retClass = true;
if ((typeInfo as ItaniumTypeInfo).HasExplicitCopyCtor ||
(typeInfo as ItaniumTypeInfo).HasExplicitDtor) {
// Section 3.1.4:
// Classes with non-default copy ctors/destructors are returned using a
// hidden argument
retByAddr = true;
}
}
ParameterInfo[] parameters = method.GetParameters ();
var ptypes = new List<Type> ();
var pmarshal = new List<ParameterMarshal> ();
// FIXME: Handle ByVal attributes
foreach (var pi in parameters) {
Type t = pi.ParameterType;
Type ptype = t;
ParameterMarshal m = ParameterMarshal.Default;
if (t == typeof (bool)) {
ptype = typeof (byte);
} else if (typeof (ICppObject).IsAssignableFrom (t) && t != typeof (CppInstancePtr)) {
if (pi.IsDefined (typeof (ByValAttribute), false)) {
m = ParameterMarshal.ClassByVal;
// Can't use an interface/cattr since the native layout type is private
// Pass it as a type argument to I<Foo> ?
var f = t.GetField ("native_layout", BindingFlags.Static|BindingFlags.NonPublic);
if (f == null || f.FieldType != typeof (Type))
throw new NotImplementedException ("Type '" + t + "' needs to have a 'native_layout' field before it can be passed by value.");
ptype = (Type)f.GetValue (null);
} else {
ptype = typeof (IntPtr);
m = ParameterMarshal.ClassByRef;
}
} else if (typeof (ICppObject).IsAssignableFrom (t)) {
// CppInstancePtr implements ICppObject
ptype = typeof (IntPtr);
}
ptypes.Add (ptype);
pmarshal.Add (m);
}
if (retByAddr) {
ptypes.Insert (0, typeof (IntPtr));
pmarshal.Insert (0, ParameterMarshal.Default);
}
return new PInvokeSignature { OrigMethod = method, ParameterTypes = ptypes, ParameterMarshallers = pmarshal, ReturnType = returnType, ReturnClass = retClass, ReturnByAddr = retByAddr };
}
}

3
src/Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs

@ -26,6 +26,9 @@ namespace Mono.VisualC.Interop.ABI { @@ -26,6 +26,9 @@ namespace Mono.VisualC.Interop.ABI {
get { return hasVirtualDtor; }
}
public bool HasExplicitCopyCtor { get; set; }
public bool HasExplicitDtor { get; set; }
public override void AddBase (CppTypeInfo baseType)
{
if (TypeComplete)

3
src/Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs

@ -25,7 +25,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -25,7 +25,7 @@ namespace Mono.VisualC.Interop.ABI {
{
}
protected override CppTypeInfo MakeTypeInfo (IEnumerable<MethodInfo> virtualMethods)
protected override CppTypeInfo MakeTypeInfo (IEnumerable<MethodInfo> methods, IEnumerable<MethodInfo> virtualMethods)
{
return new MsvcTypeInfo (this, virtualMethods, layout_type);
}
@ -190,6 +190,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -190,6 +190,7 @@ namespace Mono.VisualC.Interop.ABI {
code.Append(mangleType.ElementTypeName);
code.Append ("@@");
break;
}
return code.ToString ();

3
src/Mono.VisualC.Interop/CppTypeInfo.cs

@ -179,7 +179,8 @@ namespace Mono.VisualC.Interop { @@ -179,7 +179,8 @@ namespace Mono.VisualC.Interop {
public virtual DelegateSignature GetVTableDelegateSignature (int index)
{
MethodInfo method = VirtualMethods [index];
return new DelegateSignature () { ParameterTypes = Abi.GetParameterTypesForPInvoke (method),
var psig = Abi.GetPInvokeSignature (this, method);
return new DelegateSignature () { ParameterTypes = psig.ParameterTypes,
ReturnType = method.ReturnType,
CallingConvention = Abi.GetCallingConvention (method) };
}

Loading…
Cancel
Save