Note that there are some explanatory texts on larger screens.

plurals
  1. POC#-PInvoke: What does UnmanagedFunctionPointer do?
    primarykey
    data
    text
    <p>First, why do I ask this question? Because the Windows CE platform I am stuck with does not support this attribute. So I need to do everything to my delegate (that is getting called from C++) that the attribute normally does.</p> <p>In normal Windows I have</p> <pre><code>[UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate UInt32 UnmanagedAuthenticationEvent(UInt32 authType, UInt32 numberToDisplay, IntPtr btAddress, ref UInt32 numberOfDigits) </code></pre> <p>And it works fine. When called from C++ the <strong>return value</strong> and the <strong>ref UInt32 numberOfDigits</strong> value are both properly received from the C# layer. Now I remove the attribute and use the Windows CE required approach of passing an unmanaged function pointer to C++ via PInvoke:</p> <pre><code>_authenticationEvent = new UnmanagedAuthenticationEvent(OnReceiveUnmanagedAuthenticationEvent); _unmanagedAuthenticationEvent = Marshal.GetFunctionPointerForDelegate(_authenticationEvent); CallRegisterForAuthenticationEvent(_uBTTransportPtr, _unmanagedAuthenticationEvent); </code></pre> <p>where 'CallRegisterForAuthenticationEvent(IntPtr, IntPtr)' is the PInvoke signature.</p> <p>I have declared the following class 'variables'</p> <pre><code>private IntPtr _unmanagedAuthenticationEvent; private Delegate _authenticationEvent; private UInt32 _numberOfDigits; // the ref UInt32 passed back to C++ private UInt32 _matchValue; // the return value </code></pre> <p>to protect my delegate function pointer AND the variables passed back to C++ from garbage collection. At first I didn't add the return value and ref UInt32 value and both were garbage in C++. After doing the above, the '_numberOfDigits' value is good but the return value is junk.</p> <p>The function I am now calling from C++ looks as follows (at least to start with):</p> <pre><code> #region OnReceiveUnmanagedAuthenticationEvent // This is the function called by the unmanaged code private UInt32 OnReceiveUnmanagedAuthenticationEvent(UInt32 authType, UInt32 numberToDisplay, IntPtr btAddress, ref UInt32 numberOfDigits) { byte[] byteAddress = new byte[6]; Marshal.Copy(btAddress, byteAddress, 0, 6); string btAddressString = Common.StaticHelper.BluetoothAddressFromByteArray(byteAddress); switch (authType) { case 2: //Auth_BT_PIN: if(OnPinRequestEvent != null) { string pin = ""; OnPinRequestEvent(ref pin, btAddressString); try { _matchValue = UInt32.Parse(pin); _numberOfDigits = (uint)pin.Length; // protect value from being GCed numberOfDigits = _numberOfDigits; return _matchValue; // The case I am viewing returns here } catch(ArgumentNullException e) { Console.WriteLine("Application entered a bad PIN value. Details " + e.Message); } catch(FormatException e) { Console.WriteLine("Application entered a bad PIN value. Details " + e.Message); } catch(OverflowException e) { Console.WriteLine("Application entered a bad PIN value. Details " + e.Message); } } break; </code></pre> <p><strong>What am I missing that the return value is junk?</strong> I suppose I could return the value as a ref value in the parameters and solve my problem but I want to know how UnmanagedFunctionPointer does it so I can address other issues that might come up in this painful Windows CE implementation.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload