@ -21,19 +21,19 @@ namespace Mono.VisualC.Interop.ABI {
@@ -21,19 +21,19 @@ namespace Mono.VisualC.Interop.ABI {
//TODO: Allow interface to override default calling convention
public abstract class CppAbi {
protected ModuleBuilder implM odule ;
protected TypeBuilder implT ype ;
protected ModuleBuilder impl_m odule ;
protected TypeBuilder impl_t ype ;
protected Type interfaceType , layoutType , wrapperT ype ;
protected string library , classN ame ;
protected Type interface_type , layout_type , wrapper_t ype ;
protected string library , class_n ame ;
protected VTable vtable ;
protected FieldBuilder vtableF ield ;
protected ILGenerator ctorIL ;
protected FieldBuilder vtable_f ield ;
protected ILGenerator ctor_il ;
// default settings that subclasses can override:
protected MakeVTableDelegate makeVTableM ethod = VTable . DefaultImplementation ;
protected MemberFilter vtableOverrideF ilter = VTable . BindToSignatureAndAttribute ;
protected MakeVTableDelegate make_vtable_m ethod = VTable . DefaultImplementation ;
protected MemberFilter vtable_override_f ilter = VTable . BindToSignatureAndAttribute ;
private struct EmptyNativeLayout { }
@ -46,30 +46,30 @@ namespace Mono.VisualC.Interop.ABI {
@@ -46,30 +46,30 @@ namespace Mono.VisualC.Interop.ABI {
where NLayout : struct
//where Iface : ICppClassInstantiatable or ICppClassOverridable
{
this . implM odule = CppLibrary . interopModule ;
this . impl_m odule = CppLibrary . interopModule ;
this . library = lib ;
this . classN ame = className ;
this . interfaceT ype = typeof ( Iface ) ;
this . layoutT ype = typeof ( NLayout ) ;
this . wrapperT ype = wrapperType ;
this . class_n ame = className ;
this . interface_t ype = typeof ( Iface ) ;
this . layout_t ype = typeof ( NLayout ) ;
this . wrapper_t ype = wrapperType ;
DefineImplType ( ) ;
var properties = ( // get all properties defined on the interface
from property in interfaceT ype . GetProperties ( )
from property in interface_t ype . GetProperties ( )
select property
) . Union ( // ... as well as those defined on inherited interfaces
from iface in interfaceT ype . GetInterfaces ( )
from iface in interface_t ype . GetInterfaces ( )
from property in iface . GetProperties ( )
select property
) ;
var methods = ( // get all methods defined on the interface
from method in interfaceT ype . GetMethods ( )
from method in interface_t ype . GetMethods ( )
orderby method . MetadataToken
select method
) . Union ( // ... as well as those defined on inherited interfaces
from iface in interfaceT ype . GetInterfaces ( )
from iface in interface_t ype . GetInterfaces ( )
from method in iface . GetMethods ( )
select method
) ;
@ -77,9 +77,9 @@ namespace Mono.VisualC.Interop.ABI {
@@ -77,9 +77,9 @@ namespace Mono.VisualC.Interop.ABI {
var managedOverrides = from method in methods
where Modifiers . IsVirtual ( method )
orderby method . MetadataToken
select GetManagedOverrideTrampoline ( method , vtableOverrideF ilter ) ;
select GetManagedOverrideTrampoline ( method , vtable_override_f ilter ) ;
vtable = makeVTableM ethod ( managedOverrides . ToArray ( ) ) ;
vtable = make_vtable_m ethod ( managedOverrides . ToArray ( ) ) ;
// Implement all methods
int vtableIndex = 0 ;
@ -98,15 +98,15 @@ namespace Mono.VisualC.Interop.ABI {
@@ -98,15 +98,15 @@ namespace Mono.VisualC.Interop.ABI {
foreach ( var property in properties )
DefineProperty ( property ) ;
ctorIL . Emit ( OpCodes . Ret ) ;
return ( Iface ) Activator . CreateInstance ( implT ype . CreateType ( ) , vtable ) ;
ctor_il . Emit ( OpCodes . Ret ) ;
return ( Iface ) Activator . CreateInstance ( impl_t ype . CreateType ( ) , vtable ) ;
}
// These methods might be more commonly overridden for a given C++ ABI:
public virtual MethodType GetMethodType ( MethodInfo imethod )
{
if ( imethod . Name . Equals ( classN ame ) )
if ( imethod . Name . Equals ( class_n ame ) )
return MethodType . NativeCtor ;
else if ( imethod . Name . Equals ( "Alloc" ) )
return MethodType . ManagedAlloc ;
@ -125,7 +125,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -125,7 +125,7 @@ namespace Mono.VisualC.Interop.ABI {
// By default: native size = C++ class size + field offset padding (usually just vtable pointer)
// TODO: Only include vtable ptr if there are virtual functions? Here I guess it doesn't really matter,
// we're just allocing extra memory.
return Marshal . SizeOf ( layoutT ype ) + FieldOffsetPadding ;
return Marshal . SizeOf ( layout_t ype ) + FieldOffsetPadding ;
}
}
@ -137,20 +137,20 @@ namespace Mono.VisualC.Interop.ABI {
@@ -137,20 +137,20 @@ namespace Mono.VisualC.Interop.ABI {
protected virtual void DefineImplType ( )
{
implType = implM odule . DefineType ( implM odule . Name + "_" + interfaceT ype . Name + "_Impl" ,
impl_type = impl_m odule . DefineType ( impl_m odule . Name + "_" + interface_t ype . Name + "_Impl" ,
TypeAttributes . Class | TypeAttributes . Sealed ) ;
implT ype . AddInterfaceImplementation ( interfaceT ype ) ;
impl_t ype . AddInterfaceImplementation ( interface_t ype ) ;
vtableField = implT ype . DefineField ( "_vtable" , typeof ( VTable ) , FieldAttributes . InitOnly | FieldAttributes . Private ) ;
ConstructorBuilder ctor = implT ype . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard ,
vtable_field = impl_t ype . DefineField ( "_vtable" , typeof ( VTable ) , FieldAttributes . InitOnly | FieldAttributes . Private ) ;
ConstructorBuilder ctor = impl_t ype . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard ,
new Type [ ] { typeof ( VTable ) } ) ;
ctorIL = ctor . GetILGenerator ( ) ;
ctor_il = ctor . GetILGenerator ( ) ;
// this._vtable = (VTable passed to constructor)
ctorIL . Emit ( OpCodes . Ldarg_0 ) ;
ctorIL . Emit ( OpCodes . Ldarg_1 ) ;
ctorIL . Emit ( OpCodes . Stfld , vtableF ield ) ;
ctor_il . Emit ( OpCodes . Ldarg_0 ) ;
ctor_il . Emit ( OpCodes . Ldarg_1 ) ;
ctor_il . Emit ( OpCodes . Stfld , vtable_f ield ) ;
}
protected virtual MethodBuilder DefineMethod ( MethodInfo interfaceMethod , int index )
@ -186,7 +186,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -186,7 +186,7 @@ namespace Mono.VisualC.Interop.ABI {
MethodInfo nativeMethod ;
if ( Modifiers . IsVirtual ( interfaceMethod ) )
nativeMethod = vtable . PrepareVirtualCall ( interfaceMethod , il , vtableF ield , nativePtr , index ) ;
nativeMethod = vtable . PrepareVirtualCall ( interfaceMethod , il , vtable_f ield , nativePtr , index ) ;
else
nativeMethod = GetPInvokeForMethod ( interfaceMethod ) ;
@ -223,11 +223,11 @@ namespace Mono.VisualC.Interop.ABI {
@@ -223,11 +223,11 @@ namespace Mono.VisualC.Interop.ABI {
// C++ interface properties are either to return the VTable or to access C++ fields
if ( retType . IsGenericType & & retType . GetGenericTypeDefinition ( ) . Equals ( typeof ( CppField < > ) ) ) {
// define a new field for the property
fieldData = implT ype . DefineField ( "__" + propName + "_Data" , retType , FieldAttributes . InitOnly | FieldAttributes . Private ) ;
fieldData = impl_t ype . DefineField ( "__" + propName + "_Data" , retType , FieldAttributes . InitOnly | FieldAttributes . Private ) ;
// init our field data with a new instance of CppField
// first, get field offset
ctorIL . Emit ( OpCodes . Ldarg_0 ) ;
ctor_il . Emit ( OpCodes . Ldarg_0 ) ;
/ * TODO : Code prolly should not emit hardcoded offsets n such , in case we end up saving these assemblies in the future .
* Something more like this perhaps ? ( need to figure out how to get field offset padding into this )
@ -236,20 +236,20 @@ namespace Mono.VisualC.Interop.ABI {
@@ -236,20 +236,20 @@ namespace Mono.VisualC.Interop.ABI {
* ctorIL . Emit ( OpCodes . Ldstr , propName ) ;
* ctorIL . Emit ( OpCodes . Call , typeof ( Marshal ) . GetMethod ( "OffsetOf" ) ) ;
* /
int fieldOffset = ( ( int ) Marshal . OffsetOf ( layoutT ype , propName ) ) + FieldOffsetPadding ;
ctorIL . Emit ( OpCodes . Ldc_I4 , fieldOffset ) ;
ctorIL . Emit ( OpCodes . Newobj , retType . GetConstructor ( new Type [ ] { typeof ( int ) } ) ) ;
int fieldOffset = ( ( int ) Marshal . OffsetOf ( layout_t ype , propName ) ) + FieldOffsetPadding ;
ctor_il . Emit ( OpCodes . Ldc_I4 , fieldOffset ) ;
ctor_il . Emit ( OpCodes . Newobj , retType . GetConstructor ( new Type [ ] { typeof ( int ) } ) ) ;
ctorIL . Emit ( OpCodes . Stfld , fieldData ) ;
ctor_il . Emit ( OpCodes . Stfld , fieldData ) ;
} else if ( retType . Equals ( typeof ( VTable ) ) )
fieldData = vtableF ield ;
fieldData = vtable_f ield ;
else
throw new InvalidProgramException ( "Properties in C++ interface can only be of type CppField." ) ;
PropertyBuilder fieldProp = implT ype . DefineProperty ( propName , PropertyAttributes . None , retType , Type . EmptyTypes ) ;
PropertyBuilder fieldProp = impl_t ype . DefineProperty ( propName , PropertyAttributes . None , retType , Type . EmptyTypes ) ;
MethodAttributes methodAttr = MethodAttributes . Public | MethodAttributes . Virtual | MethodAttributes . SpecialName | MethodAttributes . HideBySig ;
MethodBuilder fieldGetter = implT ype . DefineMethod ( methodName , methodAttr , retType , Type . EmptyTypes ) ;
MethodBuilder fieldGetter = impl_t ype . DefineMethod ( methodName , methodAttr , retType , Type . EmptyTypes ) ;
ILGenerator il = fieldGetter . GetILGenerator ( ) ;
il . Emit ( OpCodes . Ldarg_0 ) ;
@ -271,13 +271,13 @@ namespace Mono.VisualC.Interop.ABI {
@@ -271,13 +271,13 @@ namespace Mono.VisualC.Interop.ABI {
if ( targetMethod = = null )
return null ;
Type delegateType = Util . GetDelegateTypeForMethodInfo ( implM odule , interfaceMethod ) ;
Type delegateType = Util . GetDelegateTypeForMethodInfo ( impl_m odule , interfaceMethod ) ;
Type [ ] parameterTypes = Util . GetMethodParameterTypes ( interfaceMethod , true ) ;
// 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 ( wrapperT ype . Name + "_" + interfaceMethod . Name + "_FromNative" , interfaceMethod . ReturnType ,
DynamicMethod trampolineIn = new DynamicMethod ( wrapper_t ype . Name + "_" + interfaceMethod . Name + "_FromNative" , interfaceMethod . ReturnType ,
parameterTypes , typeof ( CppInstancePtr ) . Module , true ) ;
Util . ApplyMethodParameterAttributes ( interfaceMethod , trampolineIn ) ;
@ -295,7 +295,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -295,7 +295,7 @@ namespace Mono.VisualC.Interop.ABI {
il . Emit ( OpCodes . Ldarg_0 ) ;
il . Emit ( OpCodes . Ldc_I4 , NativeSize ) ;
MethodInfo getManagedObj = typeof ( CppInstancePtr ) . GetMethod ( "GetManaged" , BindingFlags . Static | BindingFlags . NonPublic ) . MakeGenericMethod ( wrapperT ype ) ;
MethodInfo getManagedObj = typeof ( CppInstancePtr ) . GetMethod ( "GetManaged" , BindingFlags . Static | BindingFlags . NonPublic ) . MakeGenericMethod ( wrapper_t ype ) ;
il . Emit ( OpCodes . Call , getManagedObj ) ;
}
@ -311,7 +311,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -311,7 +311,7 @@ namespace Mono.VisualC.Interop.ABI {
protected virtual MethodInfo FindManagedOverrideTarget ( MethodInfo interfaceMethod , MemberFilter filter )
{
MemberInfo [ ] possibleMembers = wrapperT ype . FindMembers ( MemberTypes . Method , BindingFlags . Public | BindingFlags . NonPublic |
MemberInfo [ ] possibleMembers = wrapper_t ype . FindMembers ( MemberTypes . Method , BindingFlags . Public | BindingFlags . NonPublic |
BindingFlags . Instance | BindingFlags . Static , filter , interfaceMethod ) ;
if ( possibleMembers . Length > 1 )
@ -328,7 +328,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -328,7 +328,7 @@ namespace Mono.VisualC.Interop.ABI {
{
Type [ ] parameterTypes = Util . GetMethodParameterTypes ( interfaceMethod , false ) ;
MethodBuilder methodBuilder = implT ype . DefineMethod ( interfaceMethod . Name , MethodAttributes . Public | MethodAttributes . Virtual ,
MethodBuilder methodBuilder = impl_t ype . DefineMethod ( interfaceMethod . Name , MethodAttributes . Public | MethodAttributes . Virtual ,
interfaceMethod . ReturnType , parameterTypes ) ;
Util . ApplyMethodParameterAttributes ( interfaceMethod , methodBuilder ) ;
return methodBuilder ;
@ -345,7 +345,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -345,7 +345,7 @@ namespace Mono.VisualC.Interop.ABI {
Type [ ] parameterTypes = Util . GetMethodParameterTypes ( signature , true ) ;
MethodBuilder builder = implT ype . DefinePInvokeMethod ( "__$" + signature . Name + "_Impl" , library , entryPoint ,
MethodBuilder builder = impl_t ype . DefinePInvokeMethod ( "__$" + signature . Name + "_Impl" , library , entryPoint ,
MethodAttributes . Private | MethodAttributes . Static | MethodAttributes . PinvokeImpl ,
CallingConventions . Any , signature . ReturnType , parameterTypes ,
DefaultCallingConvention , CharSet . Ansi ) ;
@ -364,7 +364,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -364,7 +364,7 @@ namespace Mono.VisualC.Interop.ABI {
//TODO: Do not hard-emit native size in case assembly is saved?
il . Emit ( OpCodes . Ldc_I4 , NativeSize ) ;
if ( wrapperT ype ! = null ) {
if ( wrapper_t ype ! = null ) {
// load managed object
il . Emit ( OpCodes . Ldarg_1 ) ;
@ -424,7 +424,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -424,7 +424,7 @@ namespace Mono.VisualC.Interop.ABI {
{
// this._vtable.InitInstance (nativePtr);
il . Emit ( OpCodes . Ldarg_0 ) ;
il . Emit ( OpCodes . Ldfld , vtableF ield ) ;
il . Emit ( OpCodes . Ldfld , vtable_f ield ) ;
il . Emit ( OpCodes . Ldloc_S , nativePtr ) ;
EmitVTableOp ( il , typeof ( VTable ) . GetMethod ( "InitInstance" ) , 2 , false ) ;
}
@ -433,7 +433,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -433,7 +433,7 @@ namespace Mono.VisualC.Interop.ABI {
{
// this._vtable.ResetInstance (nativePtr);
il . Emit ( OpCodes . Ldarg_0 ) ;
il . Emit ( OpCodes . Ldfld , vtableF ield ) ;
il . Emit ( OpCodes . Ldfld , vtable_f ield ) ;
il . Emit ( OpCodes . Ldloc_S , nativePtr ) ;
EmitVTableOp ( il , typeof ( VTable ) . GetMethod ( "ResetInstance" ) , 2 , false ) ;
}
@ -454,7 +454,7 @@ namespace Mono.VisualC.Interop.ABI {
@@ -454,7 +454,7 @@ namespace Mono.VisualC.Interop.ABI {
Label dontPushOrThrow = il . DefineLabel ( ) ;
il . Emit ( OpCodes . Ldarg_0 ) ; // load this
il . Emit ( OpCodes . Ldfld , vtableF ield ) ; // load this._vtable
il . Emit ( OpCodes . Ldfld , vtable_f ield ) ; // load this._vtable
il . Emit ( OpCodes . Brfalse_S , noVirt ) ; // if (vtableInfo == null) goto noVirt
il . Emit ( OpCodes . Callvirt , method ) ; // call method