Browse Source

Fix ICppObject native-to-managed marshaling when there is no vtable

pull/1/head
Alexander Corrado 14 years ago
parent
commit
73fb2eb2a1
  1. 26
      src/Mono.Cxxi/Abi/CppAbi.cs

26
src/Mono.Cxxi/Abi/CppAbi.cs

@ -747,11 +747,11 @@ namespace Mono.Cxxi.Abi {
// Expects cppip = CppInstancePtr local // Expects cppip = CppInstancePtr local
protected virtual void EmitCreateCppObjectFromNative (ILGenerator il, Type targetType, LocalBuilder cppip) protected virtual void EmitCreateCppObjectFromNative (ILGenerator il, Type targetType, LocalBuilder cppip)
{ {
CppTypeInfo targetTypeInfo = null;
if (targetType == typeof (ICppObject)) if (targetType == typeof (ICppObject))
targetType = typeof (CppInstancePtr); targetType = typeof (CppInstancePtr);
else
il.Emit (OpCodes.Ldloca, cppip); targetTypeInfo = GetTypeInfo (targetType); // FIXME: woof. do we really have to do this?
il.Emit (OpCodes.Call, cppip_native);
// check for a native constructor (i.e. a public ctor in the wrapper that takes CppInstancePtr) // check for a native constructor (i.e. a public ctor in the wrapper that takes CppInstancePtr)
if (typeof (ICppObject).IsAssignableFrom (targetType)) { if (typeof (ICppObject).IsAssignableFrom (targetType)) {
@ -761,14 +761,19 @@ namespace Mono.Cxxi.Abi {
// Basically emitting this: // Basically emitting this:
// CppInstancePtr.ToManaged<targetType> (native) ?? new targetType (native) // CppInstancePtr.ToManaged<targetType> (native) ?? new targetType (native)
// ..but ToManaged is only called if there's a vtable (FIXME: otherwise we rewrap)
var hasWrapper = il.DefineLabel (); var hasWrapper = il.DefineLabel ();
il.Emit (OpCodes.Call, cppip_tomanaged.MakeGenericMethod (targetType)); if (targetTypeInfo != null && targetTypeInfo.VirtualMethods.Any ()) {
il.Emit (OpCodes.Dup); il.Emit (OpCodes.Ldloca, cppip);
il.Emit (OpCodes.Brtrue_S, hasWrapper); il.Emit (OpCodes.Call, cppip_native);
il.Emit (OpCodes.Pop); 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.Ldloc, cppip);
il.Emit (OpCodes.Newobj, ctor); il.Emit (OpCodes.Newobj, ctor);
@ -776,6 +781,9 @@ namespace Mono.Cxxi.Abi {
} else if (targetType.IsValueType) { } else if (targetType.IsValueType) {
// (targetType)Marshal.PtrToStructure (CppInstancePtr.Native, typeof (targetType))
il.Emit (OpCodes.Ldloca, cppip);
il.Emit (OpCodes.Call, cppip_native);
il.Emit (OpCodes.Ldtoken, targetType); il.Emit (OpCodes.Ldtoken, targetType);
il.Emit (OpCodes.Call, type_gettypefromhandle); il.Emit (OpCodes.Call, type_gettypefromhandle);
il.Emit (OpCodes.Call, marshal_ptrtostructure); il.Emit (OpCodes.Call, marshal_ptrtostructure);

Loading…
Cancel
Save