非托管代码调用vb.net回调 [英] Unmanaged code calling vb.net callback
问题描述
我正在将处理COM对象(可能用VB6编写)的事件的vb.net应用程序从框架1.1升级到WPF 2.0 / 3.5
I am upgrading vb.net app that handles the events of a COM object (possibly written in VB6) from framework 1.1 to WPF 2.0/3.5
代码: (为简便起见,简化了对象名称)
The code: (object names simplified for brevity)
public class MyClass
Private WithEvents serviceMonitor As COMOBJECT.ServiceMonitor
Public Sub New()
serviceMonitor = New COMOBJECT.ServiceMonitor()
serviceMonitor.Connect([some ip address])
End Sub
Private Sub ServiceMonitor_ServiceConnectionUp(ByVal MonitorId As Integer, ByVal UserArg As Integer) _
Handles serviceMonitor.ServiceConnectionUp
Debug.WriteLine("connection up!")
End Sub
' other similar handlers omitted
End Class
应用程序将以是预期的,但是在几秒钟之内,我就会出现访问冲突。尽管基本运行良好,但基本的回调代码类似于.net 1.1版本。
The app will get the callbacks as expected, however within a few seconds I get an Access Violation. The basic callback code is similar to the .net 1.1 version although it ran perfectly.
根据我对错误的研究,这是由垃圾收集器移动东西引起的。由于我没有将任何要处理的对象传递给DLL,所以我猜想回调是问题所在。其他人通过使用< UnmanagedFunctionPointer(CallingConvention.Cdecl)>
和/或Marshal.GetFunctionPointerForDelegate的委托来解决此问题。
According to my research on the error, it is caused by the garbage collector moving things around. Since I am not passing the DLL any objects to manipulate, I am guessing that the callbacks are the issues. Other folks have solved this via a delegate with <UnmanagedFunctionPointer(CallingConvention.Cdecl)>
and/or Marshal.GetFunctionPointerForDelegate.
不幸的是,我发现的所有示例都是DLL具有某种SetCallback(IntPtr)方法的情况。我正在使用WithEvents和Handles关键字。这是我的尝试(请注意,我删除了Handles关键字,以便可以使用AddHandler:
Unfortunately, all the examples I have found are cases where the DLL has some sort of SetCallback(IntPtr) method. I am using WithEvents and the Handles keyword. Here is my attempt (note that I removed the Handles keyword so that I can use AddHandler:
<UnmanagedFunctionPointer(CallingConvention.Cdecl)> _
Delegate Sub ServiceMonitor_ServiceConnectionUpDelegate(ByVal MonitorId As Integer, ByVal UserArg As Integer)
public class MyClass
Private WithEvents serviceMonitor As COMOBJECT.ServiceMonitor
Public Sub New()
serviceMonitor = New COMOBJECT.ServiceMonitor()
del = New ServiceMonitor_ServiceConnectionUpDelegate(AddressOf ServiceMonitor_ServiceConnectionUp)
AddHandler serviceMonitor.ServiceConnectionUp, del ' <--- Error here
serviceMonitor.Connect([some ip address])
End Sub
Private Sub ServiceMonitor_ServiceConnectionUp(ByVal MonitorId As Integer, ByVal UserArg As Integer)
Debug.WriteLine("connection up!")
End Sub
' other similar handlers omitted
End Class
我在AddHandler行上遇到的错误是: Value of类型MyClass.ServiceMonitor_ServiceConnectionUpDelegate无法转换为COMOBJECT._IServiceMonitorEvents_ServiceConnectionUpEventHandler
The error I am getting on the AddHandler line is: "Value of type MyClass.ServiceMonitor_ServiceConnectionUpDelegate cannot be converted to COMOBJECT._IServiceMonitorEvents_ServiceConnectionUpEventHandler
"
当我将鼠标悬停在上述事件处理程序上时,其签名为:
代表Sub _IServiceMonitorEvents_ServiceConnectionUpEventHandler(ByVal MonitorId为整数,ByVal UserArg为整数)
When I mouse hover the mentioned Event Handler it has a signature of: Delegate Sub _IServiceMonitorEvents_ServiceConnectionUpEventHandler(ByVal MonitorId As Integer, ByVal UserArg As Integer)
签名是相同的,所以我不确定问题出在哪里。
The signatures are identical so I'm not sure what the problem is.
问题1:如何以这种方式在AddHandler中使用委托?
问题2:是否需要涉及 Marshal.GetFunctionPointerForDelegate()
吗?
Question 1: How do I use a delegate with AddHandler in this fashion?
Question 2: Does Marshal.GetFunctionPointerForDelegate()
need to be involved? It returns an IntPtr but AddHandler wants a delegate.
预先感谢。
推荐答案
尽管我还不能100%地确定问题已得到解决,但是到目前为止,我还没有任何访问冲突。
Although I am not yet 100% certain that the issue is fixed, so far I haven't had any more access violations.
基本上,我删除了WithEvents关键字,以防止VB使用其自己的COM-> .net错误处理,而是使用库中用于C ++客户端的方法。我使用了< UnmanagedFunctionPointer(CallingConvention.Cdecl)>
并将库传递给 Marshal.GetFunctionPointerForDelegate
IntPtr。我还保留了对IntPtr的引用,尽管它可能已被矫kill过正。
Basically I removed the WithEvents keyword to prevent VB from using its own COM -> .net error handling and instead used the methods in the library intended for C++ clients. I used the <UnmanagedFunctionPointer(CallingConvention.Cdecl)>
and passed the library a Marshal.GetFunctionPointerForDelegate
IntPtr. I also kept a reference to the IntPtr althought it may have been overkill.
我很困惑,因为WithEvents处理程序在.net中工作得很好,我不得不经历所有这些事情。 1.1。主要区别在于我使用的是表单而不是类来处理回调。
I am confused that I had to go through all this since the WithEvents handlers worked perfectly in .net 1.1. The main differences was that I used a form to handle the callbacks rather than a class.
一个挥之不去的问题是,当我关闭应用程序时,调试器有时仍会运行形成。我希望这只是一个调试器怪癖。
One lingering issue is the fact that the debugger sometimes stays running when I close the apps form. I am hoping it is just a debugger quirk.
这篇关于非托管代码调用vb.net回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!