【问题标题】:Unmanaged c++ DLL in C#... WINAPI and PointersC# 中的非托管 c++ DLL ... WINAPI 和指针
【发布时间】:2011-11-11 04:51:15
【问题描述】:

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

【问题讨论】:

  • 我认为您需要声明一个委托,请参阅MSDN,您的函数可能还需要为static

标签: c# c++ pointers pinvoke dllimport


【解决方案1】:

调用函数如下......

 ZT_TRIG_STRUCT triginfo = new ZT_TRIG_STRUCT();
 IntPtr tg = IntPtr.Zero;
        tg = ZT_SetCallbackProc(ZoneTriggerCallbackProc(0,triginfo));

【讨论】:

    【解决方案2】:

    回调函数是一个方法。所以你需要传递一个方法给它。在 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);
    

    【讨论】:

      【解决方案3】:

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

      注意:请接受丹尼尔的回答,这更像是对它的补充。

      【讨论】:

      • 非常感谢...这有效....我接受丹尼尔的回答,但如果您没有给出上述解释,我仍然会迷失...非常感谢... ..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多