xamarin-macios/runtime/delegates.t4

984 строки
30 KiB
Plaintext
Исходник Обычный вид История

2016-04-21 15:19:32 +03:00
<# // vim: set filetype=cs :
#>
<#@ template language="C#" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#
var delegates = new XDelegates {
new XDelegate ("void", "void", "xamarin_gc_collect") {
WrappedManagedFunction = "GCCollect",
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_register_assembly",
"GCHandle->MonoReflectionAssembly *", "IntPtr", "assembly"
) {
WrappedManagedFunction = "RegisterAssembly",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_throw_ns_exception",
"NSException *", "IntPtr", "exc"
) {
WrappedManagedFunction = "ThrowNSException",
ExceptionHandling = false,
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
Use ExceptionDispatchInfo to keep stack traces when unhandled exceptions are marshaled. Improves bug #45742 a bit. (#1040) Example code: public override void ViewDidLoad () { throw new Exception ("USELESS"); } Current output with unhandled exceptions that are marshaled: Unhandled Exception: System.Exception: USELESS at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 [ERROR] FATAL UNHANDLED EXCEPTION: UselessExceptions.CustomException: USELESS at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 Note how the managed frame where the exception was thrown does not show up. This is because we technically catch exceptions when marshaling them, and then later we call mono_raise_exception to raise the same exception. Unfortunately that leads to overwriting the initial stack trace, and we end up with a stack trace that does not include the location where the original exception was thrown. So instead of calling mono_raise_exception to rethrow the same exception, we use ExceptionDispatchInfo, which is able to capture the stack trace for both the original exception and the new exception, producing the following output: System.Exception: USELESS at UselessExceptions.ViewController.ViewDidLoad () [0x0000c] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/ViewController.cs:27 --- End of stack trace from previous location where exception was thrown --- at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 [ERROR] FATAL UNHANDLED EXCEPTION: UselessExceptions.CustomException: USELESS at UselessExceptions.ViewController.ViewDidLoad () [0x0000c] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/ViewController.cs:27 --- End of stack trace from previous location where exception was thrown --- at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 Incidently this is how Xamarin.Android does it [1]. [1]: https://github.com/xamarin/Java.Interop/commit/9387f2fe16300ea8eb3d5270e50f0513d251bd62 https://bugzilla.xamarin.com/show_bug.cgi?id=45742
2016-10-27 21:03:11 +03:00
new XDelegate ("void", "void", "xamarin_rethrow_managed_exception",
"GCHandle", "IntPtr", "original_exception_gchandle"
) {
WrappedManagedFunction = "RethrowManagedException",
OnlyDynamicUsage = false,
},
Use ExceptionDispatchInfo to keep stack traces when unhandled exceptions are marshaled. Improves bug #45742 a bit. (#1040) Example code: public override void ViewDidLoad () { throw new Exception ("USELESS"); } Current output with unhandled exceptions that are marshaled: Unhandled Exception: System.Exception: USELESS at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 [ERROR] FATAL UNHANDLED EXCEPTION: UselessExceptions.CustomException: USELESS at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 Note how the managed frame where the exception was thrown does not show up. This is because we technically catch exceptions when marshaling them, and then later we call mono_raise_exception to raise the same exception. Unfortunately that leads to overwriting the initial stack trace, and we end up with a stack trace that does not include the location where the original exception was thrown. So instead of calling mono_raise_exception to rethrow the same exception, we use ExceptionDispatchInfo, which is able to capture the stack trace for both the original exception and the new exception, producing the following output: System.Exception: USELESS at UselessExceptions.ViewController.ViewDidLoad () [0x0000c] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/ViewController.cs:27 --- End of stack trace from previous location where exception was thrown --- at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 [ERROR] FATAL UNHANDLED EXCEPTION: UselessExceptions.CustomException: USELESS at UselessExceptions.ViewController.ViewDidLoad () [0x0000c] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/ViewController.cs:27 --- End of stack trace from previous location where exception was thrown --- at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[]) at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /work/maccore/master/xamarin-macios/src/AppKit/NSApplication.cs:98 at UselessExceptions.MainClass.Main (System.String[] args) [0x00007] in /Users/rolf/Downloads/filed-bug-test-cases-master/Xamarin/bxc45742/Main.cs:10 Incidently this is how Xamarin.Android does it [1]. [1]: https://github.com/xamarin/Java.Interop/commit/9387f2fe16300ea8eb3d5270e50f0513d251bd62 https://bugzilla.xamarin.com/show_bug.cgi?id=45742
2016-10-27 21:03:11 +03:00
new XDelegate ("GCHandle", "IntPtr", "xamarin_create_ns_exception",
"NSException *", "IntPtr", "exc"
) {
WrappedManagedFunction = "CreateNSException",
OnlyDynamicUsage = false,
},
new XDelegate ("NSException *", "IntPtr", "xamarin_unwrap_ns_exception",
"GCHandle", "IntPtr", "exc_handle"
) {
WrappedManagedFunction = "UnwrapNSException",
OnlyDynamicUsage = false,
},
new XDelegate ("char *", "IntPtr", "xamarin_get_exception_message",
"GCHandle", "IntPtr", "exc_handle") {
WrappedManagedFunction = "GetExceptionMessage",
},
new XDelegate ("char *", "IntPtr", "xamarin_print_all_exceptions_wrapper",
"GCHandle", "IntPtr", "gchandle") {
WrappedManagedFunction = "PrintAllExceptions",
},
new XDelegate ("char *", "IntPtr", "xamarin_get_object_type_fullname",
"GCHandle", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "GetObjectTypeFullName",
OnlyDynamicUsage = false,
},
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_block_wrapper_creator",
"GCHandle->MonoReflectionMethod *", "IntPtr", "method",
"int", "int", "parameter"
) {
WrappedManagedFunction = "GetBlockWrapperCreator",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_create_block_proxy",
// Don't convert the 'method' parameter, we already have a GCHandle
// available we can use.
"GCHandle", "IntPtr", "method",
2016-04-21 15:19:32 +03:00
"void *", "IntPtr", "block"
) {
WrappedManagedFunction = "CreateBlockProxy",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("id", "IntPtr", "xamarin_create_delegate_proxy",
"GCHandle->MonoReflectionMethod *", "IntPtr", "method",
"GCHandle->MonoObject *", "IntPtr", "block",
"const char *", "IntPtr", "signature",
"unsigned int", "uint", "token_ref"
) {
WrappedManagedFunction = "CreateDelegateProxy",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_register_entry_assembly",
"GCHandle->MonoReflectionAssembly *", "IntPtr", "assembly"
) {
WrappedManagedFunction = "RegisterEntryAssembly",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_class",
2016-04-21 15:19:32 +03:00
"Class", "IntPtr", "ptr"
) {
WrappedManagedFunction = "GetClass",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_selector",
2016-04-21 15:19:32 +03:00
"SEL", "IntPtr", "ptr"
) {
WrappedManagedFunction = "GetSelector",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_get_method_for_selector",
2016-04-21 15:19:32 +03:00
"Class", "IntPtr", "cls",
"SEL", "IntPtr", "sel",
"bool", "bool", "is_static",
"MethodDescription *", "IntPtr", "desc"
) {
WrappedManagedFunction = "GetMethodForSelector",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("bool", "bool", "xamarin_has_nsobject",
"id", "IntPtr", "obj"
) {
WrappedManagedFunction = "HasNSObject",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("id", "IntPtr", "xamarin_get_handle_for_inativeobject",
"GCHandle->MonoObject *", "IntPtr", "obj_handle"
) {
WrappedManagedFunction = "GetHandleForINativeObject",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_unregister_nsobject",
"id", "IntPtr", "native_obj",
// Do not automatically convert the 'managed_obj' parameter,
// in one case where call this method we already have a GCHandle
// available we can use.
"GCHandle", "IntPtr", "managed_obj"
) {
WrappedManagedFunction = "UnregisterNSObject",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_try_get_or_construct_nsobject",
2016-04-21 15:19:32 +03:00
"id", "IntPtr", "obj"
) {
WrappedManagedFunction = "TryGetOrConstructNSObjectWrapped",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_inative_object_dynamic",
2016-04-21 15:19:32 +03:00
"id", "IntPtr", "obj",
"bool", "bool", "owns",
"GCHandle->MonoReflectionType *", "IntPtr", "type"
) {
WrappedManagedFunction = "GetINativeObject_Dynamic",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
// Do not automatically unwrap the return value, because otherwise we might need to immediately wrap it in a GCHandle again.
new XDelegate ("GCHandle", "IntPtr", "xamarin_get_method_from_token",
[registrar] Use metadata tokens instead of strings to find types and methods. (#1085) Use metadata tokens instead of strings to find types and methods. This makes the code to find methods more compact (a lot less strings in the executable, and additionally in most cases a compact representation (32-bit integer) of the corresponding metadata token and additional information can be used, which results in less executable code (fewer parameters to methods, etc)), resulting in smaller executables. Size savings are around 200kb for dont link apps, and 20-60kb for linked apps (this obviously varies a lot depending on how much has to registered by the registrar). | | Before | After | Diff | |----------------|--------------:|--------------:|------------------:| | dontlink/32bit | 102.810.144 | 102.609.456 | -200.688 = -0,20% | | dontlink/64bit | 107.420.576 | 107.221.792 | -198.784 = -0,19% | | linksdk/32bit | 40.957.296 | 40.936.864 | -20.432 = -0,05% | | linksdk/64bit | 43.113.136 | 43.093.936 | -19.200 = -0,04% | | linkall/32bit | 38.410.032 | 38.348.288 |  -61.744 = -0,16% | | linkall/64bit | 40.315.200 | 40.267.344 | -47.856 = -0,12% | Additionally I've removed the `lazy_map` dictionary, which we populated at startup and was used to map between Class instances and the corresponding managed type's FullName, and instead iterate over a native array of Class -> metadata token mappings whenever we need to look up the managed type for a certain Class instance. This is slightly slower for each type we need to look up (for a non-linked app there might be a 2000-3000 entries in the native array, which would be iterated instead of using a hashtable lookup), but it's only done once per type and there's a significant startup memory improvement. For a non-linked test app I get the following using the Xamarin profiler: | | Before | After | Diff | |-------------------|--------:|--------:|----------------:| | Memory allocated | 2,8 MB | 2,4 MB | -0,4 MB = -14 % | | Objects allocated | 43678 | 38463 | -5215 = -12 % | | Private bytes | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% | | Working set | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% |
2016-11-01 21:34:56 +03:00
"unsigned int", "uint", "token_ref"
) {
WrappedManagedFunction = "GetMethodFromToken",
OnlyDynamicUsage = false,
},
[registrar] Use metadata tokens instead of strings to find types and methods. (#1085) Use metadata tokens instead of strings to find types and methods. This makes the code to find methods more compact (a lot less strings in the executable, and additionally in most cases a compact representation (32-bit integer) of the corresponding metadata token and additional information can be used, which results in less executable code (fewer parameters to methods, etc)), resulting in smaller executables. Size savings are around 200kb for dont link apps, and 20-60kb for linked apps (this obviously varies a lot depending on how much has to registered by the registrar). | | Before | After | Diff | |----------------|--------------:|--------------:|------------------:| | dontlink/32bit | 102.810.144 | 102.609.456 | -200.688 = -0,20% | | dontlink/64bit | 107.420.576 | 107.221.792 | -198.784 = -0,19% | | linksdk/32bit | 40.957.296 | 40.936.864 | -20.432 = -0,05% | | linksdk/64bit | 43.113.136 | 43.093.936 | -19.200 = -0,04% | | linkall/32bit | 38.410.032 | 38.348.288 |  -61.744 = -0,16% | | linkall/64bit | 40.315.200 | 40.267.344 | -47.856 = -0,12% | Additionally I've removed the `lazy_map` dictionary, which we populated at startup and was used to map between Class instances and the corresponding managed type's FullName, and instead iterate over a native array of Class -> metadata token mappings whenever we need to look up the managed type for a certain Class instance. This is slightly slower for each type we need to look up (for a non-linked app there might be a 2000-3000 entries in the native array, which would be iterated instead of using a hashtable lookup), but it's only done once per type and there's a significant startup memory improvement. For a non-linked test app I get the following using the Xamarin profiler: | | Before | After | Diff | |-------------------|--------:|--------:|----------------:| | Memory allocated | 2,8 MB | 2,4 MB | -0,4 MB = -14 % | | Objects allocated | 43678 | 38463 | -5215 = -12 % | | Private bytes | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% | | Working set | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% |
2016-11-01 21:34:56 +03:00
// Do not automatically unwrap the return value, because otherwise we might need to immediately wrap it in a GCHandle again.
new XDelegate ("GCHandle", "IntPtr", "xamarin_get_generic_method_from_token",
"GCHandle->MonoObject *", "IntPtr", "obj_handle",
[registrar] Use metadata tokens instead of strings to find types and methods. (#1085) Use metadata tokens instead of strings to find types and methods. This makes the code to find methods more compact (a lot less strings in the executable, and additionally in most cases a compact representation (32-bit integer) of the corresponding metadata token and additional information can be used, which results in less executable code (fewer parameters to methods, etc)), resulting in smaller executables. Size savings are around 200kb for dont link apps, and 20-60kb for linked apps (this obviously varies a lot depending on how much has to registered by the registrar). | | Before | After | Diff | |----------------|--------------:|--------------:|------------------:| | dontlink/32bit | 102.810.144 | 102.609.456 | -200.688 = -0,20% | | dontlink/64bit | 107.420.576 | 107.221.792 | -198.784 = -0,19% | | linksdk/32bit | 40.957.296 | 40.936.864 | -20.432 = -0,05% | | linksdk/64bit | 43.113.136 | 43.093.936 | -19.200 = -0,04% | | linkall/32bit | 38.410.032 | 38.348.288 |  -61.744 = -0,16% | | linkall/64bit | 40.315.200 | 40.267.344 | -47.856 = -0,12% | Additionally I've removed the `lazy_map` dictionary, which we populated at startup and was used to map between Class instances and the corresponding managed type's FullName, and instead iterate over a native array of Class -> metadata token mappings whenever we need to look up the managed type for a certain Class instance. This is slightly slower for each type we need to look up (for a non-linked app there might be a 2000-3000 entries in the native array, which would be iterated instead of using a hashtable lookup), but it's only done once per type and there's a significant startup memory improvement. For a non-linked test app I get the following using the Xamarin profiler: | | Before | After | Diff | |-------------------|--------:|--------:|----------------:| | Memory allocated | 2,8 MB | 2,4 MB | -0,4 MB = -14 % | | Objects allocated | 43678 | 38463 | -5215 = -12 % | | Private bytes | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% | | Working set | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% |
2016-11-01 21:34:56 +03:00
"unsigned int", "uint", "token_ref"
) {
WrappedManagedFunction = "GetGenericMethodFromToken",
OnlyDynamicUsage = false,
},
[registrar] Use metadata tokens instead of strings to find types and methods. (#1085) Use metadata tokens instead of strings to find types and methods. This makes the code to find methods more compact (a lot less strings in the executable, and additionally in most cases a compact representation (32-bit integer) of the corresponding metadata token and additional information can be used, which results in less executable code (fewer parameters to methods, etc)), resulting in smaller executables. Size savings are around 200kb for dont link apps, and 20-60kb for linked apps (this obviously varies a lot depending on how much has to registered by the registrar). | | Before | After | Diff | |----------------|--------------:|--------------:|------------------:| | dontlink/32bit | 102.810.144 | 102.609.456 | -200.688 = -0,20% | | dontlink/64bit | 107.420.576 | 107.221.792 | -198.784 = -0,19% | | linksdk/32bit | 40.957.296 | 40.936.864 | -20.432 = -0,05% | | linksdk/64bit | 43.113.136 | 43.093.936 | -19.200 = -0,04% | | linkall/32bit | 38.410.032 | 38.348.288 |  -61.744 = -0,16% | | linkall/64bit | 40.315.200 | 40.267.344 | -47.856 = -0,12% | Additionally I've removed the `lazy_map` dictionary, which we populated at startup and was used to map between Class instances and the corresponding managed type's FullName, and instead iterate over a native array of Class -> metadata token mappings whenever we need to look up the managed type for a certain Class instance. This is slightly slower for each type we need to look up (for a non-linked app there might be a 2000-3000 entries in the native array, which would be iterated instead of using a hashtable lookup), but it's only done once per type and there's a significant startup memory improvement. For a non-linked test app I get the following using the Xamarin profiler: | | Before | After | Diff | |-------------------|--------:|--------:|----------------:| | Memory allocated | 2,8 MB | 2,4 MB | -0,4 MB = -14 % | | Objects allocated | 43678 | 38463 | -5215 = -12 % | | Private bytes | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% | | Working set | 26,6 MB | 24,4 MB | -2,2 MB = -8,3% |
2016-11-01 21:34:56 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_inative_object_static",
2016-04-21 15:19:32 +03:00
"id", "IntPtr", "obj",
"bool", "bool", "owns",
"unsigned int", "uint", "iface_token_ref",
"unsigned int", "uint", "implementation_token_ref"
) {
WrappedManagedFunction = "GetINativeObject_Static",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_nsobject_with_type",
2016-04-21 15:19:32 +03:00
"id", "IntPtr", "obj",
"GCHandle->MonoReflectionType *", "IntPtr", "type",
"int32_t *", "out bool", "created"
) {
WrappedManagedFunction = "GetNSObjectWithType",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_dispose",
"GCHandle->MonoObject*", "IntPtr", "mobj"
) {
WrappedManagedFunction = "Dispose",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("bool", "bool", "xamarin_is_parameter_transient",
"GCHandle->MonoReflectionMethod *", "IntPtr", "method",
2016-04-21 15:19:32 +03:00
"int", "int", "parameter"
) {
WrappedManagedFunction = "IsParameterTransient",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("bool", "bool", "xamarin_is_parameter_out",
"GCHandle->MonoReflectionMethod *", "IntPtr", "method",
"int", "int", "parameter"
) {
WrappedManagedFunction = "IsParameterOut",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("void", "void", "xamarin_get_method_and_object_for_selector",
2016-04-21 15:19:32 +03:00
"Class", "IntPtr", "cls",
"SEL", "IntPtr", "sel",
"bool", "bool", "is_static",
2016-04-21 15:19:32 +03:00
"id", "IntPtr", "obj",
"GCHandle *", "ref IntPtr", "mthis",
"MethodDescription *", "IntPtr", "desc"
) {
WrappedManagedFunction = "GetMethodAndObjectForSelector",
OnlyDynamicUsage = true,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("GCHandle", "IntPtr", "xamarin_create_product_exception_for_error",
2016-04-21 15:19:32 +03:00
"int", "int", "code",
"GCHandle", "IntPtr", "inner_exception_gchandle",
2016-04-21 15:19:32 +03:00
"const char *", "string", "message"
) {
WrappedManagedFunction = "CreateProductException",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("char *", "IntPtr", "xamarin_reflection_type_get_full_name",
"GCHandle->MonoReflectionType *", "IntPtr", "type"
) {
WrappedManagedFunction = "TypeGetFullName",
OnlyDynamicUsage = false,
},
2016-04-21 15:19:32 +03:00
new XDelegate ("char *", "IntPtr", "xamarin_lookup_managed_type_name",
"Class", "IntPtr", "klass"
) {
WrappedManagedFunction = "LookupManagedTypeName",
OnlyDynamicUsage = false,
},
new XDelegate ("enum MarshalManagedExceptionMode", "MarshalManagedExceptionMode", "xamarin_on_marshal_managed_exception",
"GCHandle", "IntPtr", "exception"
) {
WrappedManagedFunction = "OnMarshalManagedException",
OnlyDynamicUsage = false,
},
new XDelegate ("enum MarshalObjectiveCExceptionMode", "MarshalObjectiveCExceptionMode", "xamarin_on_marshal_objectivec_exception",
"id", "IntPtr", "exception",
"bool", "bool", "throwManagedAsDefault"
) {
WrappedManagedFunction = "OnMarshalObjectiveCException",
OnlyDynamicUsage = false,
},
new XDelegate ("NSString *", "IntPtr", "xamarin_convert_smart_enum_to_nsstring",
"GCHandle->MonoObject *", "IntPtr", "value"
) {
WrappedManagedFunction = "ConvertSmartEnumToNSString",
OnlyDynamicUsage = true,
},
new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_convert_nsstring_to_smart_enum",
"NSString *", "IntPtr", "value",
"GCHandle->MonoReflectionType *", "IntPtr", "type"
) {
WrappedManagedFunction = "ConvertNSStringToSmartEnum",
OnlyDynamicUsage = true,
},
new XDelegate ("GCHandle", "IntPtr", "xamarin_create_runtime_exception",
"int32_t", "int", "code",
"const char *", "IntPtr", "message"
) {
WrappedManagedFunction = "CreateRuntimeException",
OnlyDynamicUsage = false,
},
new XDelegate ("GCHandle", "IntPtr", "xamarin_create_nsobject",
"GCHandle->MonoReflectionType *", "IntPtr", "type_gchandle",
"id", "IntPtr", "native_obj",
"enum NSObjectFlags", "NSObject.Flags", "flags"
) {
WrappedManagedFunction = "CreateNSObject",
OnlyDynamicUsage = false,
},
new XDelegate ("MonoAssembly *", "IntPtr", "xamarin_find_assembly",
"const char *","IntPtr", "assembly_name"
) {
WrappedManagedFunction = "FindAssembly",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_set_flags_for_nsobject",
"GCHandle", "IntPtr", "gchandle",
"uint8_t", "byte", "flags"
) {
WrappedManagedFunction = "SetFlagsForNSObject",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("uint8_t", "byte", "xamarin_get_flags_for_nsobject",
"GCHandle", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "GetFlagsForNSObject",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_bridge_set_pending_exception",
"MonoObject *", "MonoObject *", "exception_obj"
) {
WrappedManagedFunction = "SetPendingException",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("char *", "IntPtr", "xamarin_bridge_get_method_full_name",
"MonoObject *", "MonoObject *", "mobj"
) {
WrappedManagedFunction = "GetMethodFullName",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("char *", "IntPtr", "xamarin_bridge_class_get_namespace",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "ClassGetNamespace",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("char *", "IntPtr", "xamarin_bridge_class_get_name",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "ClassGetName",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("GCHandle", "IntPtr", "xamarin_bridge_create_gchandle",
"GCHandle", "IntPtr", "gchandle",
"enum XamarinGCHandleType", "GCHandleType", "type"
) {
WrappedManagedFunction = "CreateGCHandle",
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_bridge_free_gchandle",
"GCHandle", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "FreeGCHandle",
OnlyCoreCLR = true,
},
new XDelegate ("char *", "IntPtr", "xamarin_bridge_get_assembly_name",
"GCHandle", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "GetAssemblyName",
OnlyCoreCLR = true,
},
new XDelegate ("char *", "IntPtr", "xamarin_bridge_get_assembly_location",
"GCHandle", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "GetAssemblyLocation",
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_create_exception",
"enum XamarinExceptionTypes", "Runtime.ExceptionType", "type",
"const char *", "IntPtr", "arg0"
) {
WrappedManagedFunction = "CreateException",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoMethodSignature *", "IntPtr", "xamarin_bridge_method_get_signature",
"MonoObject *", "MonoObject *", "method"
) {
WrappedManagedFunction = "GetMethodSignature",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("int32_t", "int", "xamarin_bridge_sizeof",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "SizeOf",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoReferenceQueue *", "MonoObject *", "xamarin_bridge_gc_reference_queue_new",
"mono_reference_queue_callback", "IntPtr", "callback"
) {
WrappedManagedFunction = "CreateGCReferenceQueue",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_bridge_gc_reference_queue_add",
"MonoReferenceQueue *", "MonoObject *", "queue_handle",
"MonoObject *", "MonoObject *", "obj",
"void *", "IntPtr", "user_data"
) {
WrappedManagedFunction = "GCReferenceQueueAdd",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_box",
"MonoObject *", "MonoObject *", "typeobj",
"void *", "IntPtr", "value"
) {
WrappedManagedFunction = "Box",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject*", "IntPtr", "xamarin_bridge_get_monoobject",
"GCHandle", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "GetMonoObject",
OnlyCoreCLR = true,
},
new XDelegate ("MonoGHashTable *", "MonoObject *", "xamarin_bridge_mono_hash_table_create",
"GHashFunc", "IntPtr", "hash_func",
"GEqualFunc", "IntPtr", "compare_func",
"MonoGHashGCType", "int", "type"
) {
WrappedManagedFunction = "CreateMonoHashTable",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_bridge_mono_hash_table_insert",
"MonoGHashTable *", "MonoObject *", "tableobj",
"gconstpointer", "IntPtr", "key",
"MonoObject *", "MonoObject *", "valueobj"
) {
WrappedManagedFunction = "MonoHashTableInsert",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_mono_hash_table_lookup",
"MonoGHashTable *", "MonoObject *", "tableobj",
"gconstpointer", "IntPtr", "key"
) {
WrappedManagedFunction = "MonoHashTableLookup",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_get_method_declaring_type",
"MonoObject *", "MonoObject *", "mobj"
) {
WrappedManagedFunction = "GetMethodDeclaringType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "IntPtr", "xamarin_bridge_object_get_type",
"MonoObject *", "IntPtr", "gchandle"
) {
WrappedManagedFunction = "ObjectGetType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_isinstance",
"GCHandle", "IntPtr", "gchandle",
"GCHandle", "IntPtr", "type"
) {
WrappedManagedFunction = "IsInstance",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_runtime_invoke_method",
"MonoObject *", "MonoObject *", "method",
"MonoObject *", "MonoObject *", "instance",
"void**", "IntPtr", "parameters"
) {
WrappedManagedFunction = "InvokeMethod",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_type_to_class",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "TypeToClass",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoClass *", "MonoObject *", "xamarin_bridge_lookup_class",
"enum XamarinLookupTypes", "Runtime.TypeLookup", "type"
) {
WrappedManagedFunction = "LookupType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_is_enum",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "IsEnum",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_get_enum_basetype",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "GetEnumBaseType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_is_byref",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "IsByRef",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_is_valuetype",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "IsValueType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_is_nullable",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "IsNullable",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_get_element_class",
"MonoObject *", "MonoObject *", "classobj"
) {
WrappedManagedFunction = "GetElementClass",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "xamarin_bridge_get_nullable_element_type",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "GetNullableElementType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_is_delegate",
"MonoObject *", "MonoObject *", "typeobj"
) {
WrappedManagedFunction = "IsDelegate",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("bool", "bool", "xamarin_bridge_is_class_of_type",
"MonoObject *", "MonoObject *", "classobj",
"enum XamarinLookupTypes", "Runtime.TypeLookup", "type"
) {
WrappedManagedFunction = "IsClassOfType",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("char *", "IntPtr", "xamarin_bridge_string_to_utf8",
"MonoObject *", "MonoObject *", "obj"
) {
WrappedManagedFunction = "StringToUtf8",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoString *", "MonoObject *", "xamarin_bridge_new_string",
"const char *", "IntPtr", "text"
) {
WrappedManagedFunction = "NewString",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoArray *", "MonoObject *", "xamarin_bridge_create_array",
"MonoClass *", "MonoObject *", "typeobj",
"uint64_t", "ulong", "elements"
) {
WrappedManagedFunction = "CreateArray",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("uint64_t", "ulong", "xamarin_bridge_get_array_length",
"MonoArray *", "MonoObject *", "arrayobj"
) {
WrappedManagedFunction = "GetArrayLength",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "mono_array_setref",
"MonoArray *", "MonoObject *", "arrayobj",
"uint64_t", "ulong", "index",
"MonoObject *", "MonoObject *", "valueobj"
) {
WrappedManagedFunction = "SetArrayObjectValue",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_bridge_set_array_struct_value",
"MonoArray *", "MonoObject *", "arrayobj",
"uint64_t", "ulong", "index",
"MonoClass *", "MonoObject *", "typeobj",
"void *", "IntPtr", "valueptr"
) {
WrappedManagedFunction = "SetArrayStructValue",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("MonoObject *", "MonoObject *", "mono_array_get",
"MonoArray *", "MonoObject *", "arrayobj",
"uint64_t", "ulong", "index"
) {
WrappedManagedFunction = "GetArrayObjectValue",
OnlyDynamicUsage = false,
OnlyCoreCLR = true,
},
new XDelegate ("void", "void", "xamarin_retain_nativeobject",
"GCHandle->MonoObject *", "IntPtr", "obj"
) {
WrappedManagedFunction = "RetainNativeObject",
OnlyDynamicUsage = false,
},
new XDelegate ("bool", "bool", "xamarin_attempt_retain_nsobject",
"GCHandle->MonoObject *", "IntPtr", "obj"
) {
WrappedManagedFunction = "AttemptRetainNSObject",
OnlyDynamicUsage = false,
},
new XDelegate ("bool", "bool", "xamarin_invoke_conforms_to_protocol",
"id", "IntPtr", "obj",
"Protocol *", "IntPtr", "protocol"
) {
WrappedManagedFunction = "InvokeConformsToProtocol",
},
2016-04-21 15:19:32 +03:00
};
delegates.CalculateLengths ();
#><#+
class Arg
{
public string MangledCType;
public string ExposedCType; // the CType exposed to native code
public string InterfaceCType; // the CType as interfaced with managed code
2016-04-21 15:19:32 +03:00
public string MType;
public string Name;
public bool IsGCHandleConversion => MangledCType.Contains ("->");
public Arg (string mangledCType, string mType, string name)
{
MangledCType = mangledCType;
var is_conv = IsGCHandleConversion;
var interfaced = is_conv ? "GCHandle" : mangledCType;
var exposed = is_conv ? XDelegate.GetConvertedGCHandleType (mangledCType) : mangledCType;
ExposedCType = exposed;
InterfaceCType = interfaced;
MType = mType;
Name = name;
}
public bool IsVoid => ExposedCType == "void";
2016-04-21 15:19:32 +03:00
}
class XDelegates : List<XDelegate>
{
public void CalculateLengths ()
{
foreach (var x in this) {
MaxEntryPointLength = Math.Max (MaxEntryPointLength, x.EntryPoint.Length);
MaxCReturnTypeLength = Math.Max (MaxCReturnTypeLength, x.ReturnType.ExposedCType.Length);
2016-04-21 15:19:32 +03:00
x.Delegates = this;
}
}
public int MaxEntryPointLength;
public int MaxCReturnTypeLength;
}
class XDelegate
{
public Arg ReturnType;
2016-04-21 15:19:32 +03:00
public string EntryPoint;
public List<Arg> Arguments;
public string WrappedManagedFunction;
public bool ExceptionHandling = true;
// Detemines whether the function is only used by the dynamic registrar (in which case we might be able to link the function away if the static registrar is being used)
public bool OnlyDynamicUsage;
public bool OnlyCoreCLR;
2016-04-21 15:19:32 +03:00
public string DelegateName {
get {
if (EntryPoint.StartsWith ("xamarin_"))
return EntryPoint.Substring ("xamarin_".Length);
if (EntryPoint.StartsWith ("mono_", StringComparison.Ordinal))
return EntryPoint.Substring ("mono_".Length);
throw new NotImplementedException ($"Unknown prefix for {EntryPoint}");
}
}
public static string GetConvertedGCHandleType (string type)
{
return type.Substring ("GCHandle->".Length);
}
2016-04-21 15:19:32 +03:00
public XDelegates Delegates;
public XDelegate (string cReturnType, string mReturnType, string entryPoint, params string [] arguments)
{
ReturnType = new Arg (cReturnType, mReturnType, string.Empty);
2016-04-21 15:19:32 +03:00
EntryPoint = entryPoint;
if (arguments.Length % 3 != 0)
throw new Exception (string.Format ("Export arguments params must be a multiple of 3 to form a set of (c type, managed name, name) triples for {0}", entryPoint));
if (!entryPoint.StartsWith ("xamarin_", StringComparison.Ordinal) && !entryPoint.StartsWith ("mono_", StringComparison.Ordinal))
throw new Exception ("All entry points must start with 'xamarin_' or 'mono_'");
2016-04-21 15:19:32 +03:00
Arguments = new List<Arg> ();
for (var i = 0; i < arguments.Length; i += 3)
Arguments.Add (new Arg (arguments [i], arguments [i + 1], arguments [i + 2]));
}
public string Function {
get {
var sb = new StringBuilder ();
// This function generates the helper function that actually calls the managed delegate
// It supports converting input arguments of MonoObject* (and equivalent types) to GCHandle,
// and converting GCHandle return values to MonoObject* (or equivalent types). In both cases
// the GCHandle will be freed before the generated function returns.
sb.AppendLine (ReturnType.ExposedCType);
sb.Append (EntryPoint);
sb.Append (" (");
sb.Append (CArgumentSignatureExposed);
sb.AppendLine (")");
sb.AppendLine ("{");
if (ExceptionHandling && OnlyDynamicUsage) {
sb.AppendLine ($"\tif (delegates.{DelegateName} == NULL) {{");
sb.AppendLine ($"\t\t*exception_gchandle = create_linked_away_exception (\"{DelegateName}\");");
sb.AppendLine ($"\t\treturn{(ReturnType.IsVoid ? string.Empty : $" ({ReturnType.ExposedCType}) 0")};");
sb.AppendLine ($"\t}}");
} else {
sb.AppendLine ($"#if DEBUG");
sb.AppendLine ($"\tif (delegates.{DelegateName} == NULL) {{");
sb.AppendLine ($"\t\tNSLog (@PRODUCT \": The managed function {DelegateName} could not be loaded.\");");
sb.AppendLine ($"\t\txamarin_assertion_message (\"The managed function {DelegateName} could not be loaded.\");");
sb.AppendLine ($"\t}}");
sb.AppendLine ($"#endif");
}
var invoke_args = new StringBuilder ();
var post_invoke = new StringBuilder ();
for (var i = 0; i < Arguments.Count; i++) {
var arg = Arguments [i];
if (i > 0)
invoke_args.Append (", ");
if (arg.IsGCHandleConversion) {
// Convert to GCHandle before calling the managed function
var argname = $"{arg.Name}__handle";
sb.AppendLine ($"\tGCHandle {argname} = xamarin_gchandle_new ((MonoObject *) {arg.Name}, false);");
invoke_args.Append (argname);
// and free the GCHandle after returning from the managed function
post_invoke.AppendLine ($"\txamarin_gchandle_free ({argname});");
} else {
invoke_args.Append (arg.Name);
}
}
if (ExceptionHandling)
sb.AppendLine ("\tGCHandle exception_gchandle_tmp = INVALID_GCHANDLE;");
sb.Append ("\t");
if (!ReturnType.IsVoid) {
sb.Append ($"{ReturnType.ExposedCType} rv = ");
// Unwrap the GCHandle and free it
if (ReturnType.IsGCHandleConversion)
sb.Append ("xamarin_gchandle_unwrap (");
}
sb.Append ("delegates.");
sb.Append (DelegateName);
sb.Append (" (");
sb.Append (invoke_args);
if (ExceptionHandling) {
if (Arguments.Count > 0)
sb.Append (", ");
sb.Append ("&exception_gchandle_tmp");
}
if (ReturnType.IsGCHandleConversion)
sb.Append (")");
sb.AppendLine (");");
sb.Append (post_invoke);
if (ExceptionHandling) {
sb.AppendLine ("#if defined (CORECLR_RUNTIME)");
sb.AppendLine ("\tif (exception_gchandle == NULL) {");
sb.AppendLine ("\t\tif (exception_gchandle_tmp != INVALID_GCHANDLE)");
sb.AppendLine ("\t\t\txamarin_handle_bridge_exception (exception_gchandle_tmp, __func__);");
sb.AppendLine ("\t} else {");
sb.AppendLine ("\t\t*exception_gchandle = exception_gchandle_tmp;");
sb.AppendLine ("\t}");
sb.AppendLine ("#else");
sb.AppendLine ("\t*exception_gchandle = exception_gchandle_tmp;");
sb.AppendLine ("#endif");
}
if (!ReturnType.IsVoid)
sb.AppendLine ("\treturn rv;");
sb.AppendLine ("}");
return sb.ToString ();
}
2016-04-21 15:19:32 +03:00
}
public string SimpleEntryPoint {
get {
if (EntryPoint.StartsWith ("xamarin_"))
return EntryPoint.Substring ("xamarin_".Length);
if (EntryPoint.StartsWith ("mono_", StringComparison.Ordinal))
return EntryPoint.Substring ("mono_".Length);
throw new NotImplementedException ($"Unknown prefix for {EntryPoint}");
2016-04-21 15:19:32 +03:00
}
}
public string AlignEntryPoint {
get {
return new string (' ', Delegates.MaxEntryPointLength - EntryPoint.Length);
}
}
public string AlignCReturnType {
get {
return new string (' ', Delegates.MaxCReturnTypeLength - ReturnType.ExposedCType.Length);
2016-04-21 15:19:32 +03:00
}
}
string CFormatArgs (string empty, bool nameOnly, bool exposed = false, bool functionDeclaration = false)
2016-04-21 15:19:32 +03:00
{
var builder = new StringBuilder ();
foreach (var arg in Arguments) {
if (!nameOnly) {
builder.Append (exposed ? arg.ExposedCType : arg.InterfaceCType);
2016-04-21 15:19:32 +03:00
builder.Append (' ');
}
builder.Append (arg.Name);
builder.Append (", ");
}
if (Arguments.Count > 0)
builder.Length -= 2;
2016-04-21 15:19:32 +03:00
if (ExceptionHandling) {
if (Arguments.Count > 0)
builder.Append (", ");
if (nameOnly) {
builder.Append ("exception_gchandle");
} else if (functionDeclaration) {
builder.Append ("GCHandle *exception_gchandle = NULL");
} else {
builder.Append ("GCHandle *exception_gchandle");
}
}
2016-04-21 15:19:32 +03:00
return builder.ToString ();
}
string MFormatArgs (string empty, bool nameOnly)
{
var builder = new StringBuilder ();
foreach (var arg in Arguments) {
if (!nameOnly) {
builder.Append (arg.MType);
builder.Append (' ');
} else if (arg.MType.StartsWith ("out ")) {
builder.Append ("out ");
} else if (arg.MType.StartsWith ("ref ")) {
builder.Append ("ref ");
}
builder.Append (arg.Name);
builder.Append (", ");
}
if (Arguments.Count > 0)
builder.Length -= 2;
2016-04-21 15:19:32 +03:00
if (ExceptionHandling) {
if (nameOnly) {
// nothing to do
} else {
if (Arguments.Count > 0)
builder.Append (", ");
builder.Append ("out IntPtr exception_gchandle");
}
}
2016-04-21 15:19:32 +03:00
return builder.ToString ();
}
public string CArgumentSignature {
get { return CFormatArgs ("void", nameOnly: false); }
}
public string CArgumentSignatureExposed {
get { return CFormatArgs ("void", nameOnly: false, exposed: true); }
}
public string CArgumentSignatureFunctionDeclaration {
get { return CFormatArgs ("void", nameOnly: false, exposed: true, functionDeclaration: true); }
}
2016-04-21 15:19:32 +03:00
public string CArgumentNames {
get { return CFormatArgs (String.Empty, nameOnly: true); }
}
public string MArgumentSignature {
get { return MFormatArgs ("", nameOnly: false); }
}
public string MArgumentNames {
get { return MFormatArgs (String.Empty, nameOnly: true); }
}
}
#>