繁体   English   中英

从本机C DLL调用回调到VB6

[英]Invoke callback into VB6 from native C DLL

我正在尝试获取本机C函数来调用VB6应用程序中的回调。 在VB中,代码如下所示:

Private Declare Sub StartUp Lib "library.dll" (ByVal cbAddress As Long)

Public Sub MySub
    Call StartUp(AddressOf MyCallback)
End Sub

Public Sub MyCallback(ByVal str As String)
' Use str in UI
End Sub

当我从VB6 IDE运行此程序时,一切正常:调用回调,并且可以使用str参数没有问题。 但是,当我将VB6应用程序编译为exe时,调用回调时该应用程序将崩溃。 从我在谷歌搜索中可以看出,这似乎是某种线程问题。 有人建议使用Win32 SendMessage避免这种线程问题。 我不太清楚该怎么做。 我会在回调中调用SendMessage吗? 我如何在主线程上收到此消息? 另外,如何将字符串传递给SendMessage?

编辑:我刚刚发现: Vb6应用程序可以在IDE中工作,但可执行文件崩溃

但是,我最初的问题仍然存在。

Edit2:我也应该包括在C代码中。 这是定义和调用回调的方式:

typedef void (__stdcall *FUNCPTR)(BSTR);
int wslen = MultiByteToWideChar(CP_ACP, 0, cstr, strlen(cstr), 0, 0);
BSTR bstr = SysAllocStringLen(0, wslen);
MultiByteToWideChar(CP_ACP, 0, cstr, strlen(cstr), bstr, wslen);
((FUNCPTR) _cbAddress)(bstr);
SysFreeString(bstr);

同样,当从IDE调用时,这很好用...

显然,最理想的选择是确保回调始终在VB应用程序的主线程上发生。 否则,您将不得不对应用程序中的窗口使用SendMessage()来利用Window自身在Windows之间的编组能力。

以前,我编写了一个VB应用程序,该应用程序从DLL进行了回调,该DLL用于与远程控件集成。 但是DLL使用了另一个线程来与硬件集成。 在我的回调中,我使用带有WM_COPYDATA SendMessage()将数据编组到主VB线程,该线程由子类化代码拾取。

当然,由于您正在编写C DLL,而您只是在传递回ASCII文本,因此您可以跳过几个步骤,而不必编写回调过程或具有子类代码。 只需使用SetWindowText() API调用将文本直接写到TextBox 确保在始终加载的表单上使用Visible = False创建此TextBox 然后,您只需要使用以下代码:

BOOL WINAPI SetWindowText(
  _In_      HWND hWnd,
  _In_opt_  LPCTSTR lpString
);

HWND m_hWndTextBox

void StartUp(HWND hWndTextBox)
{
    m_hWndTextBox = hWndTextBox;
    // other stuff
}

void Callback(char *cstr) {
    SetWindowText(m_hWndTextBox, cstr);
}

和VB代码:

' Form "Form1" with text box "Text1".

Private Declare Sub StartUp Lib "library.dll" (ByVal hWndTextBox As Long)

Public Sub MySub
    Call StartUp(Text1.hWnd)
End Sub

Private Sub Text1_Change()
    DoStuffWithDLLUpdateString Text1.Text
End Sub

而且,您甚至不必将字符串转换为BSTR-VB会为您执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM