Comment passer une structure de VB à c

Signaler
Messages postés
42
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
17 mai 2006
-
Messages postés
42
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
17 mai 2006
-
Bonjour,
Tout d'abord je tiens à préciser que je n'ai pas trouvé de réponse complète à mon problème sur internet. (en tout cas je n'arriva pas à l'appliquer :-) )

Je dispose d'une structure en VBA qui est la suivante:
Public Type Modele
nomModele As String
tableau() As Variant
loi() As Variant
pctPart As Double
taux As Double
tauxRVNI As Double
End Type

je la rempli dans mon application en vb. Jusque là tout va bien.
Ensuite j'appelle une fonction d'une dll que j'ai créée en passant par référence un modele que j'ai initialisé :

methodeRenouvelants(monModele, Resultat)

La variable Resultat est passée par référence pour que code VB puisse lire le résultat.

Bien entendu, j'ai déclaré ma dll précédemment:
Public Declare Function methodeRenouvelants Lib........

Je cherche à récupérer cette structure dans ma dll, mais je bloque un peu. Je ne sais pas trop comment definir ma structure dans le code c, et ce afin que le c récupère tout ca correctement.

Précision: J'ai essayé sans structure avec la méthode suivante :
methodeRenouvelants(monModele.tableau, monModele.loi, monModele.pctPart, monModele.taux, monModele.tauxRVNI, 0, 0.1, Resultat) et ca fonctionne nickel. L'avantage de cette solution est que je n'ai pas à passer de string (de type BSTR) à la dll.

Pour information, je sais qu'il faut récupérer les tableaux de variant par des " LPSAFEARRAY *tableau ". Je sais également qu'il faut récupérer les types "double" de vb par des types "double" de C.
Je pense qu'il y a un problème de taille de caractère entre les string de VB et les chaines de c.

Mes questions:
Comment récupérer la structure dans le code c (en la passant par référence depuis VB bien sur)?
D'autre part comment puis-je faire pour passer cette fichue chaien de caractère (nomModele)?

pfiouuuu!!! j'savais pas que je pouvais écrire des message saussi longs. J'espère que je en vous ai pas trop soulé.

merci

6 réponses

Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
Ta chaine est en fait un POINTEUR bstr, j'ai déjà traité cela ici:
TRAITER STRING VB PAR DLL C/C++ (WIN32)
http://www.cppfrance.com/code.aspx?ID=30115

Jette aussi un oeil ici pour les tableaux:
GENERATEUR DE TABLEAUX DE NOMBRES POUR VB/VBA
http://www.vbfrance.com/code.aspx?ID=33938
Le code de la dll est dans un txt joint, il y a un peu d'asm mais ce sont les algos de génération des nombres, pas obligé de t'y arrêter.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
42
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
17 mai 2006

Merci pour ta réponse


je vais jeter un oeil et je tiens la communauté au courant.
++
Messages postés
42
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
17 mai 2006

Bon, aprés avoir jeté un coup d'oeil sur tes sources, je n'arrive toujours pas à résoudre mon problème. Je sais passer un tableau de vb à une dll. Je sais aussi passer une chaine de caractère. Par contre je n'arrive pas à passer un double par référence (j'ai retourné le truc dans tous les sens :-) ).

Je récapitule mon problème :

je souhaite passer une instance de la STRUCTURE suivante de VB à ma DLL.

Public Type Modele
nomModele As String
pctPart As Double
taux As Double
tauxRVNI As Double
tableau() As Variant
loi() As Variant
End Type

L'instance de cette classe est bien évidemment passée par référence à la dll.

Quelqu'un aurait-il une idée pour le code du coté c ?

je fais un truc qui fait planter mon excel (je code du vba)

typedef struct Modele{
LPSTR nomModele;
double pctPart;
double taux;
double tauxRVNI;
LPSAFEARRAY *tableau;
LPSAFEARRAY *loi;
} MonModele;



EXPORT
long WINAPI methodeDll( MonModele *lpModele ) {


LPSTR nomModele;
LPSAFEARRAY *tableau;
LPSAFEARRAY *loi;
double pctPart;
double taux;
double tauxRVNI;


long nTab,pTab, nLoi, pLoi;
VARIANT HUGEP *tabData, *loiData;
HRESULT hr;


//affectation des champs du modèle//
nomModele = lpModele->nomModele;
tableau = lpModele->tableau;
loi = lpModele->loi;
taux = lpModele->taux;
tauxRVNI = lpModele->tauxRVNI;
pctPart = lpModele->pctPart;



//Récupération de la taille des données//
SafeArrayGetUBound(*tableau,1,&nTab);
SafeArrayGetUBound(*tableau,2,&pTab);
SafeArrayGetUBound(*loi,1,&nLoi);
SafeArrayGetUBound(*loi,2,&pLoi);



//Récupération des données//
hr = SafeArrayAccessData(*tableau,(void HUGEP **)&tabData);
if (FAILED(hr)) {
MessageBox (NULL, "Impossible de lire le tableau !" , "DLL Message", MB_ICONHAND);
return -1;
}
hr = SafeArrayAccessData(*loi,(void HUGEP **)&loiData);
if (FAILED(hr)) {
MessageBox (NULL, "Impossible de lire la loi de renouvellement !" , "DLL Message", MB_ICONHAND);
return -1;
}
.......
return 0;
}

Merci pour l'aide
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
Faut réduire la struct pour les tests, fais par exemple une struct avec 2 double et essaie de les relire.
Faut procéder étape par étape pour cerner le problème.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
42
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
17 mai 2006

OK c'est ce que j'ai fait.

Voici les résultats quand je construis différentes structures:

1 double => fonctionne
2 double => fonctionne
1 LPSTR => fonctionne (equivalent de char *)
2 LPSTR => fonctionne

quand je mélange :
LPSTR s
double d
ca foire

Par contre dans l'autre sens
double d
LPSTR s
ca fonctionne!

Je pense que ce doit être lié à la taille de la chaine de caractères que le C ne connaît pas. Bref, la chaîne de caractère est passée par pointeur dans la structure. Par contre je ne sais pas ce qu'il en est du double.

Etant donné que je dois rajouter des LPSAFEARRAY ca va être coton .
Je pense mettre ma chaine de caractère à la fin, les doubles au début, et les tableaux au milieu.

Ton avis?
Messages postés
42
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
17 mai 2006

Ok

Bon, pour information, j'ai réussi à contourner le problème de la manière suivante (quand je dis problème, je parle du fait que je dois placer mon LPSTR à la fin de ma structure). Ca donne ça : (en epérant que ca servira à quelqu'un un jour...)

coté VB :
---------

Public Declare Function testStructG Lib "c:\test\test.dll" (s As structG) As Long

Public Type structG
d1 As Double
d2 As Double
d3 As Double
t() As Variant
l() As Variant
s As String
End Type

Sub passageStructure()
Dim s As structG

s12.d1 = 1002.2
s12.d2 = 3210254
s12.d3 = 32.01001
s12.t = Sheets("data").Range("B2:B8").Value
s12.l = Sheets("data").Range("C2:C8").Value
s12.s = "structureG ok"
testStructG s12

End Sub

Coté C:
--------

#include <windows.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ole2.h>


#define EXPORT __declspec(dllexport)

typedef struct G{
double d1;
double d2;
double d3;
LPSAFEARRAY t;
LPSAFEARRAY l;
LPSTR s;
}structG;

EXPORT
long WINAPI testStructG( structG * g ){

VARIANT HUGEP * pData, lData;
double d1;
double d2;
double d3;
LPSAFEARRAY t;
LPSAFEARRAY l;
char msg[256];

d1 = g->d1;
d2 = g->d2;
d3 = g->d3;

//affichage des types doubles
sprintf(msg,"%lf,%lf,%lf",d1,d2,d3);
MessageBox (NULL, msg , "DLL Message", 0);


//affichage du tableau t
t = g->t;
sprintf(msg,"%x",&t);
MessageBox (NULL, msg , "DLL Message", 0);
SafeArrayGetUBound(t,1,&nT);
SafeArrayGetUBound(t,2,&mT);
sprintf(msg,"%i x %i",nT,mT);
MessageBox (NULL, msg , "DLL Message", 0);


//affichage du tableau l
l = g->l;
sprintf(msg,"%x",&l);
MessageBox (NULL, msg , "DLL Message", 0);
SafeArrayGetUBound(l,1,&nL);
SafeArrayGetUBound(l,2,&mL);
sprintf(msg,"%i x %i",nT,mT);
MessageBox (NULL, msg , "DLL Message", 0);


//affichage de la chaine de caractère
MessageBox(NULL, g->s, "DLL Message", 0);


return 0;
}