2010-04-02 111 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