private static void Create(ReverseWrapper<TFunction> reverseFunctionWrapper, IntPtr functionPtr) { Mutex.MakeReverseWrapperMutex.WaitOne(); var reloadedFunctionAttribute = FunctionAttribute.GetAttribute<TFunction>(); // CDECL is hot path, as our TFunction will already be CDECL, we marshal if it's anything else. if (! reloadedFunctionAttribute.Equals(new FunctionAttribute(CallingConventions.Cdecl))) reverseFunctionWrapper.WrapperPointer = Create(functionPtr, reloadedFunctionAttribute); Mutex.MakeReverseWrapperMutex.ReleaseMutex(); }
private static void Create(ReverseWrapper <TFunction> reverseFunctionWrapper, IntPtr functionPtr) { var attribute = FunctionAttribute.GetAttribute <TFunction>(); // Hot path: Don't create wrapper if both conventions are already compatible. var funcPtrAttribute = Misc.TryGetAttributeOrDefault <TFunction, UnmanagedFunctionPointerAttribute>(); if (!attribute.IsEquivalent(funcPtrAttribute)) { reverseFunctionWrapper.WrapperPointer = Wrapper.Create <TFunction>(functionPtr, attribute.GetEquivalent(funcPtrAttribute), attribute); } }
/// <summary> /// Creates the <see cref="Wrapper"/> which allows you to call a function with a custom calling /// convention as if it were a CDECL function. /// </summary> /// <param name="functionAddress">Address of the function to reverse wrap..</param> public static TFunction Create <TFunction>(long functionAddress) { var attribute = FunctionAttribute.GetAttribute <TFunction>(); IntPtr wrapperFunctionPointer = (IntPtr)functionAddress; // Hot path: CDECL functions require no wrapping. if (!attribute.Equals(new FunctionAttribute(CallingConventions.Cdecl))) { wrapperFunctionPointer = Create <TFunction>((IntPtr)functionAddress, attribute); } return(Marshal.GetDelegateForFunctionPointer <TFunction>(wrapperFunctionPointer)); }