title: C#-PInvoke: What does UnmanagedFunctionPointer do?
body: <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>