From 474409c62560f73aa953e66d9444fbacb0c73660 Mon Sep 17 00:00:00 2001 From: Alexander Corrado Date: Fri, 22 Jul 2011 02:54:16 -0400 Subject: [PATCH] Do not always assume ICppObject; support structs too --- src/Mono.Cxxi/Abi/CppAbi.cs | 58 ++++++++++++---------------- src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs | 6 ++- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/Mono.Cxxi/Abi/CppAbi.cs b/src/Mono.Cxxi/Abi/CppAbi.cs index b1677c4..35381d9 100644 --- a/src/Mono.Cxxi/Abi/CppAbi.cs +++ b/src/Mono.Cxxi/Abi/CppAbi.cs @@ -741,22 +741,7 @@ namespace Mono.Cxxi.Abi { return wrapper_to_typeinfo [otherWrapperType]; } - // Does the above passthru at runtime. - // This is perhaps a kludgy/roundabout way for pulling the type info for another - // ICppObject at runtime, but I think this keeps the wrappers clean. - protected virtual void EmitGetTypeInfo (ILGenerator il, Type targetType) - { - // check for a subclass constructor (i.e. a public ctor in the wrapper that takes CppTypeInfo) - var ctor = targetType.GetConstructor (BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance, null, new Type [] { typeof (CppTypeInfo) }, null); - if (ctor == null) - throw new InvalidProgramException (string.Format ("Type `{0}' implements ICppObject but does not contain a public constructor that takes CppTypeInfo", targetType)); - il.Emit (OpCodes.Newobj, dummytypeinfo_ctor); - il.Emit (OpCodes.Dup); - il.Emit (OpCodes.Newobj, ctor); - il.Emit (OpCodes.Pop); - il.Emit (OpCodes.Call, dummytypeinfo_getbase); - } // Expects cppip = CppInstancePtr local protected virtual void EmitCreateCppObjectFromNative (ILGenerator il, Type targetType, LocalBuilder cppip) @@ -764,29 +749,36 @@ namespace Mono.Cxxi.Abi { if (targetType == typeof (ICppObject)) targetType = typeof (CppInstancePtr); - // check for a native constructor (i.e. a public ctor in the wrapper that takes CppInstancePtr) - var ctor = targetType.GetConstructor (BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance, null, new Type [] { typeof (CppInstancePtr) }, null); - if (ctor == null) - throw new InvalidProgramException (string.Format ("Type `{0}' implements ICppObject but does not contain a public constructor that takes CppInstancePtr", targetType)); - - - // Basically emitting this: - // CppInstancePtr.ToManaged (native) ?? new targetType (native) - - var hasWrapper = il.DefineLabel (); - il.Emit (OpCodes.Ldloca, cppip); il.Emit (OpCodes.Call, cppip_native); - il.Emit (OpCodes.Call, cppip_tomanaged.MakeGenericMethod (targetType)); - il.Emit (OpCodes.Dup); - il.Emit (OpCodes.Brtrue_S, hasWrapper); - il.Emit (OpCodes.Pop); + // check for a native constructor (i.e. a public ctor in the wrapper that takes CppInstancePtr) + if (typeof (ICppObject).IsAssignableFrom (targetType)) { + var ctor = targetType.GetConstructor (BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance, null, new Type [] { typeof (CppInstancePtr) }, null); + if (ctor == null) + throw new InvalidProgramException (string.Format ("Type `{0}' implements ICppObject but does not contain a public constructor that takes CppInstancePtr", targetType)); - il.Emit (OpCodes.Ldloc, cppip); - il.Emit (OpCodes.Newobj, ctor); + // Basically emitting this: + // CppInstancePtr.ToManaged (native) ?? new targetType (native) + + var hasWrapper = il.DefineLabel (); + + il.Emit (OpCodes.Call, cppip_tomanaged.MakeGenericMethod (targetType)); + il.Emit (OpCodes.Dup); + il.Emit (OpCodes.Brtrue_S, hasWrapper); + il.Emit (OpCodes.Pop); + + il.Emit (OpCodes.Ldloc, cppip); + il.Emit (OpCodes.Newobj, ctor); + + il.MarkLabel (hasWrapper); - il.MarkLabel (hasWrapper); + } else if (targetType.IsValueType) { + + il.Emit (OpCodes.Ldtoken, targetType); + il.Emit (OpCodes.Call, marshal_ptrtostructure); + il.Emit (OpCodes.Unbox, targetType); + } } /** diff --git a/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs b/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs index 6d7ccb1..1669f91 100644 --- a/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs +++ b/src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs @@ -224,8 +224,10 @@ namespace Mono.Cxxi.Abi { { returnValue = il.DeclareLocal (typeof (CppInstancePtr)); - EmitGetTypeInfo (il, method.ReturnType); - il.Emit (OpCodes.Call, typeinfo_nativesize); + if (typeof (ICppObject).IsAssignableFrom (method.ReturnType)) + il.Emit (OpCodes.Ldc_I4, GetTypeInfo (method.ReturnType).NativeSize); + else if (method.ReturnType.IsValueType) + il.Emit (OpCodes.Ldc_I4, Marshal.SizeOf (method.ReturnType)); il.Emit (OpCodes.Newobj, cppip_fromsize); il.Emit (OpCodes.Stloc, returnValue);