如何在从C ++调用的VB.NET中编写回调函数

时间:2017-05-29 20:26:24

标签: c++ vb.net

我正在使用C ++编写的DLL,该DLL由外部源提供文档,但没有源代码。

我需要在VB.NET中实例化一个回调函数,在某些情况下由C ++模块调用。提供的文档看起来像;

功能我打电话来建立回叫;

extern "C" int EDIT_API Do_RunStuff( 
const int MyID, 
const char* my_tag1, 
const char* my_tag2, 
const char* some_data,
const int some_options,
int* some_count,
void* owner,
void* callback_func);

回叫功能的模板是;

typedef void (*CallbackRunStuff)( void* ptr2object, const char* my_tag1, 
const char* my_name, const char* some_code, 
const char* error_type, const char* message );

所以我创建了我的VB.NET代码;

声明函数;

Declare Function  Do_RunStuff Lib "SOME.DLL" (ByVal MyID As Integer, _
                                              ByVal my_tag1 As String, _
                                              ByVal my_tag2 As String, _
                                              ByVal some_data As String, _
                                              ByVal some_options As Integer, _
                                              ByRef some_count As Integer, _
                                              ByRef owner As IntPtr, _
                                              ByRef callback_func As IntPtr) As Integer

调用该函数;

Dim objEditsErrorHandler As New editsErrorHandlerDelegate(AddressOf editsErrorHandler)
Dim objThis As GCHandle = GCHandle.Alloc(Me)
Dim ptrEditsErrorHandler As IntPtr = Marshal.GetFunctionPointerForDelegate(objEditsErrorHandler)
Dim ptrThis As IntPtr = GCHandle.ToIntPtr(objThis)
intResult = Do_RunStuff(_AnID, strTag1, strTag2, strSomeData, someValue, SomeCount, ptrThis, ptrEditsErrorHandler)

创建委托;

Public Delegate Sub editsErrorHandlerDelegate(ByRef objThis As IntPtr, ByVal strEditTag As String, ByVal strEditName As String, ByVal strAdminCode As String, ByVal strErrorType As String, ByVal strMessage As String)

创建功能;

Public Sub editsErrorHandler(ByRef objThis As IntPtr, ByVal strEditTag As String, ByVal strEditName As String, ByVal strAdminCode As String, ByVal strErrorType As String, ByVal strMessage As String)
    Debug.Print("*****====================*****")
    Debug.Print("Error Type: " & strErrorType)
    Debug.Print("Message: " & strMessage)
End Sub

当不需要回叫时,一切都在游泳。当它尝试回拨editsErrorHandler时,程序将中止;

  

中发生了未处理的“System.AccessViolationException”类型异常

我不知道从哪里开始。 DLL的开发人员是C ++人员,没有答案。

任何想法?

编辑1

在文档中,他们展示了如何从C ++调用

呼叫可能回拨的模块;

FMyEngineClass->Do_RunStuff(my_tag1, my_tag2, some_data,
    some_options, &some_count, this, ShowErrorMessages);

回调函数的定义;

static void ShowErrorMessages(void* caller, const char* my_tag1,
    const char* some_name, const char* some_code,
    const char* error_type, const char* message)

2 个答案:

答案 0 :(得分:0)

如果其他人发现这一点,我的特殊问题就是一条愚蠢的行;

<UnmanagedFunctionPointer(CallingConvention.Cdecl)>

这需要立即进行;

Public Delegate Sub editsErrorHandlerDelegate(ByRef objThis As IntPtr, ByVal strEditTag As String, ByVal strEditName As String, ByVal strAdminCode As String, ByVal strErrorType As String, ByVal strMessage As String)
像这样;

<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Sub editsErrorHandlerDelegate(ByRef objThis As IntPtr, ByVal strEditTag As String, ByVal strEditName As String, ByVal strAdminCode As String, ByVal strErrorType As String, ByVal strMessage As String)

答案 1 :(得分:0)

你不需要显式地使用GCHandle来传递函数指针,而且我很怀疑你是否正确使用了API声明(你似乎正在逃避它,因为你似乎没有使用参数你错了)。

我相信以下是正确的:

<UnmanagedFunctionPointer(CallingConvention.Cdecl)> _
Public Delegate Sub editsErrorHandlerDelegate(ByVal objThis As IntPtr, <[In]()> ByVal strEditTag As String, <[In]()> ByVal strEditName As String, <[In]()> ByVal strAdminCode As String, <[In]()> ByVal strErrorType As String, <[In]()> ByVal strMessage As String)

Declare Function Do_RunStuff Lib "SOME.DLL" (ByVal MyID As Integer, _
                                             ByVal my_tag1 As String, _
                                             ByVal my_tag2 As String, _
                                             ByVal some_data As String, _
                                             ByVal some_options As Integer, _
                                             ByRef some_count As Integer, _
                                             ByVal owner As WhateverClassThisResidesIn, _
                                             ByVal callback_func As editsErrorHandlerDelegate) As Integer


Public Sub editsErrorHandler(ByVal objThis As IntPtr, ByVal strEditTag As String, ByVal strEditName As String, ByVal strAdminCode As String, ByVal strErrorType As String, ByVal strMessage As String)
    Debug.Print("*****====================*****")
    Debug.Print("Error Type: " & strErrorType)
    Debug.Print("Message: " & strMessage)
End Sub
Do_RunStuff(_AnID, strTag1, strTag2, strSomeData, someValue, someCount, Me, AddressOf editsErrorHandler)

如果WhateverClassThisResidesIn是结构,则需要ByRef owner As ThatStructure