[英]Unmanaged c++ DLL in C#… WINAPI and Pointers
我被要求在我的項目中集成網絡攝像頭ZoneTrigger。 該站點提供的SDK也是C ++的樣本。 我已經能夠完成很少的功能。 我被卡住的地方是回調完成的功能。 示例c ++中的代碼回調函數
ZT_SetCallbackProc(ZoneTriggerCallbackProc);
//在頭文件中
typedef int (WINAPI *f_ZT_SetCallbackProc) (void *proc);
/*
Sets up the callback function for your application.
The proc should be declared like this:
int WINAPI ZoneTriggerCallbackProc(int MessageType, ZT_TRIG_STRUCT *trigInfo);
MessageType may be one of the following:
0: Zone Trigger sends a trig. The trigInfo contains data about the hot spots that generated the trig.
1: Zone Trigger has started and is notifying us that it is ready. This only occurs when Zone Trigger starts after the interface DLL is loaded.
2: Zone Trigger is shutting down. You application may need to know this. If Zone Trigger is started again, your application will get message 1.
3: Zone Trigger's Hot spot scheme has changed (a Hot Spot was added or deleted)
*/
我的c#代碼:
[DllImport("ZTcom.dll")]
private static extern IntPtr ZT_SetCallbackProc(int ZoneTriggerCallbackProc);
private unsafe int ZoneTriggerCallbackProc(int MessageType, ref ZT_TRIG_STRUCT trigInfo)
{
switch (MessageType)
{
case 0: //Trig from a Zone Trigger hot spot
// string s1 = new string(trigInfo.SpotName);
MessageBox.Show("Got a trig from spot" + trigInfo.SpotIndex.ToString()+ s1 );
break;
case 1: //Zone Trigger has started and is notifying us that it is ready
MessageBox.Show("Zone Trigger issued a ready notification.\r\n");
break;
case 2: //Zone Trigger is shutting down
MessageBox.Show("Zone Trigger has left the building.\r\n");
break;
case 3: //Hot spot scheme updated, you might want yo re-enumerate the hot spots
MessageBox.Show("Zone Trigger's hot spots have been updated.\r\n");
break;
}
return 0;
}
到目前為止我已達到...但我不明白如何調用ZT_SetCallbackProc函數?
IntPtr tg = IntPtr.Zero;
tg = ZT_SetCallbackProc(ZoneTriggerCallbackProc);
這給出了ZoneTriggerCallbackProc是方法組的錯誤。 請幫助...提前謝謝。
丹尼爾的回答是簡單快捷的。 如果您不想遇到問題(因為GC會收集委托,導致AccessViolationException),您將需要執行以下操作。
Daniel的類型/ pinvoke聲明(完整性):
// int WINAPI ZoneTriggerCallbackProc(int MessageType, ZT_TRIG_STRUCT *trigInfo);
delegate int ZoneTriggerCallbackProc(int messageType, ref ZT_TRIG_STRUCT trigInfo);
[DllImport("ZTcom.dll")]
private static extern IntPtr ZT_SetCallbackProc(ZoneTriggerCallbackProc callbackProc);
在您的包裝器類中,保持對委托的引用,以便GC在設置回調時不收集委托。
public class ZoneTrigger : CriticalFinalizerObject
{
private ZoneTriggerCallbackProc _zoneTriggerCallback;
private IntPtr _zoneTriggerCallbackCookie;
public ZoneTrigger()
{
_zoneTriggerCallback = ZoneTriggerCallback;
// Why not just do it here?
_zoneTriggerCallbackCookie = NativeMethods.ZT_SetCallbackProc(_zoneTriggerCallback);
if (_zoneTriggerCallbackCookie == IntPtr.Zero)
throw new Exception("Failed to set callback");
}
private unsafe int ZoneTriggerCallback(int MessageType, ref ZT_TRIG_STRUCT trigInfo)
{
// ...
}
~ZoneTrigger()
{
var oldCookie = Interlocked.Exchange(ref _zoneTriggerCallback, IntPtr.Zero);
if (oldCookie != IntPtr.Zero)
ZT_ClearCallbackProc(oldCookie);
}
}
注意:請接受丹尼爾的回答,這更像是一個補充。
回調函數是一種方法。 所以你需要傳遞一個方法。 在C#中,您可以通過定義委托來實現:
// int WINAPI ZoneTriggerCallbackProc(int MessageType, ZT_TRIG_STRUCT *trigInfo);
delegate int ZoneTriggerCallbackProc(int messageType, ref ZT_TRIG_STRUCT trigInfo);
[DllImport("ZTcom.dll")]
private static extern IntPtr ZT_SetCallbackProc(ZoneTriggerCallbackProc callbackProc);
調用該功能如下....
ZT_TRIG_STRUCT triginfo = new ZT_TRIG_STRUCT();
IntPtr tg = IntPtr.Zero;
tg = ZT_SetCallbackProc(ZoneTriggerCallbackProc(0,triginfo));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.