【问题标题】:C++ VB6 interfacing problemC++ VB6 接口问题
【发布时间】:2010-04-02 16:09:57
【问题描述】:

我正在努力解决这个问题,任何见解都将不胜感激:

我有一个 C++ exe,它从主线程中的某些硬件获取数据并在另一个线程(线程 2)中处理它。

我使用一个 c++ dll 来提供一些从线程 2 调用的数据处理函数。

我有一个需求,在VB6中再做一组数据处理函数。因此,我创建了一个 VB6 dll,使用插件 vbAdvance 来 创建一个标准的dll。

当我从主线程调用这个 VB6 dll 中的函数时,一切都按预期工作。

当我在线程 2 中从这个 VB6 dll 调用函数时,我遇到了访问冲突。

我已经将错误追溯到 CopyMemory 命令,如果在主线程的调用中使用它,那似乎没问题 但是在来自进程线程的调用中,它会导致异常。为什么会这样?据我了解,线程共享相同的地址空间。

这是我的 VB dll 中的代码

Public Sub UserFunInterface(ByVal in1ptr As Long, ByVal out1ptr As Long, ByRef nsamples As Long)
Dim myarray1() As Single
Dim myarray2() As Single
Dim i As Integer
ReDim myarray1(0 To nsamples - 1) As Single
ReDim myarray2(0 To nsamples - 1) As Single


With tsa1din(0)  ' defined as safearray1d in a global definitions module
    .cDims = 1
    .cbElements = 4
    .cElements = nsamples
    .pvData = in1ptr
End With

With tsa1dout
    .cDims = 1
    .cbElements = 4
    .cElements = nsamples
    .pvData = out1ptr
End With
CopyMemory ByVal VarPtrArray(myarray1), VarPtr(tsa1din(0)), 4
CopyMemory ByVal VarPtrArray(myarray2), VarPtr(tsa1dout), 4

For i = 0 To nsamples - 1
    myarray2(i) = myarray1(i) * 2
Next i
ZeroMemory ByVal VarPtrArray(myarray1), 4
ZeroMemory ByVal VarPtrArray(myarray2), 4


End Sub

更新:-

感谢您的所有 cmets,我实际上找到了一种解决方法,可以满足我的需要。我已将数组的所有指针操作放入 VB dll 中的单独函数中,我在设置例程期间从 C++ 应用程序的主线程调用此函数。然后处理线程调用 dll 中的另一个例程,该例程仅包含要对数组数据执行的计算(并且没有 CopyMemory 命令)。这似乎有效。

【问题讨论】:

  • 为什么您必须费尽心思在 VB6 中编写一个 DLL 并破解它以公开标准导入?只是感兴趣。
  • 我知道这没有多大意义,但我的客户要求我在 VB 中提供一个接口,允许用户创建自定义数学处理函数以应用于我的系统正在获取的数据和加工。我的标准处理函数是通过 c++ dll 提供的。我没有在我的 c++ 应用程序中使用 com,这就是我选择“破解”VB dll 的原因。这只是更广泛的计算密集型实时采集和控制系统的一个方面,我必须与之交互并与之一起工作。

标签: c++ multithreading dll vb6


【解决方案1】:

您必须在第二个线程上初始化 COM在调用 VB6 DLL 导出之前初始化 VB6 运行时。因此,首先在工作线程上调用CoInitilize,然后从VB6 ActiveX DLL 创建一个虚拟对象(立即释放它),然后调用该函数。

您可以在导出文件中执行这两个步骤,但要复杂得多。您不能调用内部 VB 函数,也不能声明 API 函数,只能调用 typelib 导入的函数。我的线程入口函数是这样开始的:

'--- initialize COM libs
Call CoInitialize(0)
'--- create a VB6 object
Call CoCreateInstance(CLSIDFromProgID(PROGID_DUMMY), Nothing, CLSCTX_INPROC_SERVER, VBGUIDFromString(STR_IID_IUnknown), Nothing)
On Error GoTo ...

所有 API 函数都来自线程类型库。这是一个函数,它可以告诉你 VB 运行时是否在当前线程上运行

Private Function pvIsVbRuntime() As Boolean
    Dim lIdx            As Long

    lIdx = GetModuleHandle("MSVBVM60.DLL")
    lIdx = GetProcAddress(lIdx, "__vbaSetSystemError")
    Call RtlMoveMemory(lIdx, ByVal lIdx + 9, 4)
    Call RtlMoveMemory(lIdx, ByVal lIdx, 4)
    If TlsGetValue(lIdx) <> 0 Then
        pvIsVbRuntime = True
    End If
End Function

所有 API 函数也是从 typelib 导入的。它很老套,我只在 SP6 上测试过。

无论如何,我认为 vbAdvance 插件应该很好地记录您的问题。您最好在 C++ 代码中“准备”工作线程。

【讨论】:

  • 感谢您的回复,我将尝试实施。不幸的是,vbAdvance 文档没有涵盖任何这些内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多