首先,我为什么问这个问题? 因为我坚持使用的Windows CE平台不支持此属性。所以我需要对我的委托(即从C++调用)执行一切属性通常的操作。C#-PInvoke:UnmanagedFunctionPointer做什么?
在正常的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实现中的其他问题。
没有合理的方法来处理这个问题,当调用约定错误时,堆栈会不平衡。你*必须*改变你的C代码并声明函数指针__stdcall。 –
我的理解是,Windows CE只有一个调用约定,那就是Winapi,我猜它是CDECL。有没有一种方法可以在不使用UnmanagedFunctionPointer属性的情况下声明调用约定? –
也许Windows CE不需要这个声明,因为它只支持一个调用约定。 –