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# レイヤーから適切に受信されます。ここで属性を削除し、アンマネージ関数ポインターを PInvoke 経由で C++ に渡すという Windows CE で必要なアプローチを使用します。

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

戻り値がジャンクであるために何が欠けていますか? 値をパラメーターの参照値として返して問題を解決できると思いますが、UnmanagedFunctionPointer がどのようにそれを行うかを知りたいので、この厄介な Windows CE 実装で発生する可能性のある他の問題に対処できます。

4

1 に答える 1

3

それが指定するのは、関数呼び出し規約だけです。WindowsCE では、呼び出し規則が 1 つしかないため、この属性は不要であり、存在しません。したがって、両方のプラットフォームをサポートしようとする場合は、この属性を使用して条件付きコンパイルが必要になります。

于 2013-08-04T13:05:10.660 に答える