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

How to write a callback function in VB.NET called from C++

本文关键字:写回 回调 函数 NET VB 调用      更新时间:2023-10-16

我正在使用由文档提供的外部源提供的C 编写的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)

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

<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)

您不需要明确使用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