Do not always assume ICppObject; support structs too

This commit is contained in:
Alexander Corrado 2011-07-22 02:54:16 -04:00
Родитель abbcad5411
Коммит 474409c625
2 изменённых файлов: 29 добавлений и 35 удалений

Просмотреть файл

@ -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<targetType> (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<targetType> (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);
}
}
/**

Просмотреть файл

@ -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);