まず、なぜ私はこの質問をするのですか?私が立ち往生している 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 実装で発生する可能性のある他の問題に対処できます。