c# - C# 中的非托管 C++ DLL ... WINAPI 和指针

标签 c# c++ pointers pinvoke dllimport

我被要求在我的项目中集成网络摄像头 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 是一个方法组的错误。请帮忙...提前致谢。

最佳答案

丹尼尔的 answer有简单快捷的路线。如果您不想遇到问题(因为委托(delegate)可能会被 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);  

在您的包装类中,保留对委托(delegate)的引用,以便 GC 在设置回调时不会收集委托(delegate)。

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# - C# 中的非托管 C++ DLL ... WINAPI 和指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7318170/

相关文章:

c++ - C 和 C++ 中带有 const 限定符的数组指针

c++ - 在指向对象的动态指针数组上插入新元素

c# - 应用程序的业务层是否应该能够访问 Session 对象?

c# - string.Join(string, string[]) 返回 "System.String[]"

c++ - condition_variable,引用和线程:谁拥有锁?

c++ - 带有 boost 变体递归包装器的字符串解析器

c++ - 为什么这些全局变量具有命名空间范围?

c - 将指针传递给函数

c# - 如何从 Azure 函数返回 AcceptedAtRouteResult?

C# - Linq 将泛型列表转换为自定义类