1

首先,我为什么要问这个问题?因为我坚持的 Windows CE 平台不支持这个属性。所以我需要对我的委托(从 C++ 调用)做所有属性通常做的事情。

在普通的 Windows 中,我有

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]        
public delegate UInt32 UnmanagedAuthenticationEvent(UInt32 authType, UInt32 numberToDisplay, IntPtr btAddress, ref UInt32 numberOfDigits)

它工作正常。当从 C++ 调用时,返回值ref UInt32 numberOfDigits值都从 C# 层正确接收。现在我删除该属性并使用 Windows CE 所需的方法通过 PInvoke 将非托管函数指针传递给 C++:

_authenticationEvent = new UnmanagedAuthenticationEvent(OnReceiveUnmanagedAuthenticationEvent);
_unmanagedAuthenticationEvent = Marshal.GetFunctionPointerForDelegate(_authenticationEvent);
CallRegisterForAuthenticationEvent(_uBTTransportPtr, _unmanagedAuthenticationEvent);

其中 'CallRegisterForAuthenticationEvent(IntPtr, IntPtr)' 是 PInvoke 签名。

我已经声明了以下类“变量”

private IntPtr _unmanagedAuthenticationEvent;
private Delegate _authenticationEvent;
private UInt32 _numberOfDigits; // the ref UInt32 passed back to C++
private UInt32 _matchValue;     // the return value

保护我的委托函数指针和传递回 C++ 的变量不被垃圾收集。起初我没有添加返回值和 ref UInt32 值,它们在 C++ 中都是垃圾。完成上述操作后,'_numberOfDigits' 值很好,但返回值是垃圾。

我现在从 C++ 调用的函数如下所示(至少开始时):

    #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;

我错过了什么返回值是垃圾?我想我可以将值作为参数中的 ref 值返回并解决我的问题,但我想知道 UnmanagedFunctionPointer 是如何做到的,以便我可以解决这个痛苦的 Windows CE 实现中可能出现的其他问题。

4

1 回答 1

3

原来它指定的只是函数调用约定。在 WindowsCE 上,只有一个调用约定,因此不需要此属性,因此不存在。因此,如果尝试同时支持这两种平台,则需要对使用此属性进行条件编译。

于 2013-08-04T13:05:10.660 回答