2010-04-02 116 views
0

我撕裂了我的头发试图解决这一个,任何见解将不胜感激:C++ VB6的接口问题

我有一个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 

更新: -

感谢您的意见,其实我已经找到了解决办法,做什么,我需要它做。我已经把所有的数组指针操作放到了VB dll的独立函数中,我在安装例程期间从C++应用程序的主线程中调用了这个函数。处理线程然后调用dll中的另一个例程,该例程仅包含要对阵列数据执行的计算(并且不包含CopyMemory命令)。这似乎工作。

+0

为什么你必须经历所有的麻烦才能在VB6中编写DLL并破解它以暴露标准的导入?只是感兴趣。 – 2010-04-05 00:51:01

+0

我知道它没有什么意义,但我的客户要求我在VB中提供一个接口,允许用户创建自定义的数学处理函数来应用于我的系统正在获取和处理的数据。我的标准处理函数通过C++ dll提供。我没有在我的C++应用程序中使用com,这就是为什么我选择“破解”VB DLL。这只是一个更广泛的计算密集型实时采集和控制系统的一个方面,我不得不与之交互并协同工作。 – Roshan 2010-04-05 09:19:13

回答

1

您必须在第二个线程上初始化COM 在调用VB6 DLL导出之前初始化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函数都来自线程typelib。下面是一个函数,它可以告诉你,如果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函数。这很不好,我只在SP6上测试过它。

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

+0

感谢您在回复中的时间,我会尽力实施。不幸的是,vbAdvance文档没有涉及到这一点。 – Roshan 2010-04-05 09:49:44