Skip to content

Commit 1cfa6d6

Browse files
authored
[monoapi] Add mono_method_get_unmanaged_callers_only_ftnptr (#66007)
Like `RuntimeMethodHandle.GetFunctionPointer`, but callable from native code
1 parent faa272f commit 1cfa6d6

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

src/mono/mono/metadata/external-only.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "assembly-internals.h"
2424
#include "external-only.h"
2525
#include <mono/metadata/threads.h>
26+
#include <mono/metadata/mono-private-unstable.h>
2627
#include "threads-types.h"
2728
#include "jit-info.h"
2829

@@ -696,3 +697,25 @@ mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
696697
{
697698
return mono_mem_manager_mp_contains_addr (mono_mem_manager_get_ambient (), vtable_slot);
698699
}
700+
701+
/**
702+
* mono_method_get_unmanaged_callers_only_ftnptr:
703+
* \param method method to generate a thunk for.
704+
* \param error set on error
705+
*
706+
* Returns a function pointer for calling the given UnmanagedCallersOnly method from native code.
707+
* The function pointer will use the calling convention specified on the UnmanagedCallersOnly
708+
* attribute (or the default platform calling convention if omitted).
709+
*
710+
* Unlike \c mono_method_get_unmanaged_thunk, minimal marshaling is done to the method parameters in
711+
* the wrapper. See
712+
* https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute?view=net-6.0
713+
* The method must be static and only use blittable argument types. There is no exception out-argument.
714+
*
715+
*
716+
*/
717+
void*
718+
mono_method_get_unmanaged_callers_only_ftnptr (MonoMethod *method, MonoError *error)
719+
{
720+
MONO_EXTERNAL_ONLY_GC_UNSAFE (gpointer, mono_method_get_unmanaged_wrapper_ftnptr_internal (method, TRUE, error));
721+
}

src/mono/mono/metadata/icall.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6045,11 +6045,19 @@ ves_icall_System_Environment_get_TickCount64 (void)
60456045

60466046
gpointer
60476047
ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method, MonoError *error)
6048+
{
6049+
return mono_method_get_unmanaged_wrapper_ftnptr_internal (method, FALSE, error);
6050+
}
6051+
6052+
void*
6053+
mono_method_get_unmanaged_wrapper_ftnptr_internal (MonoMethod *method, gboolean only_unmanaged_callers_only, MonoError *error)
60486054
{
60496055
/* WISH: we should do this in managed */
60506056
if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (method))) {
60516057
method = mono_marshal_get_managed_wrapper (method, NULL, (MonoGCHandle)0, error);
60526058
return_val_if_nok (error, NULL);
6059+
} else {
6060+
g_assert (!only_unmanaged_callers_only);
60536061
}
60546062
return mono_get_runtime_callbacks ()->get_ftnptr (method, error);
60556063
}

src/mono/mono/metadata/object-internals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,4 +2137,7 @@ int
21372137
mono_string_instance_is_interned (MonoString *str);
21382138
#endif
21392139

2140+
gpointer
2141+
mono_method_get_unmanaged_wrapper_ftnptr_internal (MonoMethod *method, gboolean only_unmanaged_callers_only, MonoError *error);
2142+
21402143
#endif /* __MONO_OBJECT_INTERNALS_H__ */

src/native/public/mono/metadata/details/mono-private-unstable-functions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ MONO_API_FUNCTION(MONO_RT_EXTERNAL_ONLY MonoAssemblyLoadContextGCHandle, mono_al
2626
MONO_API_FUNCTION(void, mono_register_bundled_satellite_assemblies, (const MonoBundledSatelliteAssembly **assemblies))
2727

2828
MONO_API_FUNCTION(MonoBundledSatelliteAssembly *, mono_create_new_bundled_satellite_assembly, (const char *name, const char *culture, const unsigned char *data, unsigned int size))
29+
30+
31+
MONO_API_FUNCTION(MONO_RT_EXTERNAL_ONLY void*, mono_method_get_unmanaged_callers_only_ftnptr, (MonoMethod *method, MonoError *error))

0 commit comments

Comments
 (0)