C ++ VB6接口问题

时间:2010-04-02 16:09:58

标签: c++ multithreading dll vb6

我正在试图解决这个问题,我会非常感激任何见解:

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

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

我需要在VB6中创建另一组数据处理函数。因此我使用加载项vbAdvance创建了一个VB6 dll 创建一个标准的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

更新: -

感谢您的所有评论,我实际上已经找到了一项解决方案来完成我需要它做的事情。我已经把数组的所有指针操作放到VB dll中的单独函数中,我在安装例程期间从C ++应用程序的主线程调用此函数。然后,处理线程调用dll中的另一个例程,该例程仅包含要对数组数据执行的计算(并且不包含CopyMemory命令)。这似乎有效。

1 个答案:

答案 0 :(得分:1)

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

您可以在导出中执行这两个步骤,但这要复杂得多。您不能调用内部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

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

无论如何,我认为你的问题应该用vbAdvance加载项很好地记录下来。你最好用C ++代码“准备”工作线程。