2010-04-02 4 views
0

Je me arracher les cheveux à essayer de résoudre celui-ci, des idées sera très apprécié:C++ problème d'interface VB6

J'ai un C++ exe qui acquiert des données de certains matériels dans le thread principal et traite en un autre fil (fil 2).

-je utiliser un C++ dll pour fournir des fonctions de traitement de données qui sont appelées à partir de fils 2.

J'ai une obligation de faire une autre série de fonctions de traitement de données dans VB6. J'ai donc créé un dll VB6, en utilisant le complément vbAdvance à créer une DLL standard.

Lorsque j'appelle des fonctions à partir de cette DLL VB6 à partir du thread principal, tout fonctionne exactement comme prévu.

Lorsque j'appelle des fonctions de cette DLL VB6 dans le thread 2, j'obtiens une violation d'accès.

J'ai tracé l'erreur à la commande CopyMemory, il semblerait que si cela est utilisé dans l'appel du thread principal, c'est bien mais dans un appel du thread de processus, il provoque une exception. Pourquoi cela devrait-il être ainsi? Pour autant que je sache, les threads partagent le même espace d'adressage.

Voici le code de mon dll VB

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 

MISE À JOUR: -

Merci pour tous vos commentaires, j'ai effectivement trouvé un travail autour qui fait ce que je dois à faire. J'ai mis toutes les manipulations de pointeur pour les tableaux dans une fonction séparée dans la DLL VB, j'appelle cette fonction du thread principal de l'application C++ pendant les routines d'installation. Le thread de traitement appelle ensuite une autre routine dans la dll qui contient uniquement les calculs à effectuer sur les données du tableau (et pas de commandes CopyMemory). Cela semble fonctionner.

+0

Pourquoi devez-vous passer par tous les problèmes pour écrire une DLL dans VB6 et la pirater pour exposer les importations standard? Juste intéressé. –

+0

Je sais que cela n'a pas beaucoup de sens, mais mon client exige que je fournisse une interface dans VB qui permette aux utilisateurs de créer des fonctions de traitement mathématique personnalisées à appliquer aux données que mon système acquiert et traite. Mes fonctions de traitement standard sont fournies via une DLL C++. Je n'ai pas utilisé com dans mon application C++, c'est pourquoi j'ai choisi de "pirater" la dll VB. Ce n'est qu'un aspect d'un système d'acquisition et de contrôle en temps réel, plus intensif en termes de calcul, que je dois interfacer et travailler à côté. – Roshan

Répondre

1

Vous devez initialiser COM sur le deuxième thread et initialiser VB6 run-time avant d'appeler l'exportation DLL VB6. Donc, appelez d'abord CoInitilize sur le thread de travail, ensuite créez un objet factice à partir de la DLL ActiveX VB6 (abdez-le immédiatement), puis appelez la fonction.

Vous pouvez effectuer ces deux étapes dans votre exportation, mais c'est beaucoup plus compliqué. Vous ne pouvez pas appeler la fonction intrinsèque VB, ni les fonctions API déclarées, seulement les fonctions importées par typelib. Ma fonction d'entrée de thread commence comme suit:

'--- 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 ... 

où toutes les fonctions de l'API proviennent d'un typelib de thread. Voici une fonction qui peut vous dire si l'exécution VB est sur thread courant

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 

Toute la fonction API importée de typelib aussi. C'est hacky et je l'ai testé sur SP6 seulement.

Quoi qu'il en soit, je pense que votre type de problèmes devrait être bien documenté avec le complément vbAdvance. Vous feriez mieux de "préparer" le thread de travail dans le code C++.

+0

Merci pour votre temps à répondre, je vais essayer de mettre en œuvre cela. Malheureusement, la documentation de vbAdvance ne couvre aucun de ces problèmes. – Roshan