Salut,
Un peu de contexte d'abord :
J'ai écrit un programme à but scientifique qui (entre autres choses) traite des données pouvant se présenter dans des formats différents selon leur origine. Mon programme gère pour l'instant 2 formats très courants mais évidemment tous les formats ne sont pas gérés. Pour ces formats non gérés, je voulais donner la possibilité à leurs utilisateurs d'écrire une DLL à partir d'un template que je fournis. Cette DLL s'interfacerait avec le programme principal pour remplir les conteneurs de données.
Mon implémentation :
A ce stade encore expérimental, la DLL se contente de recevoir un TStringList du programme principal pour le remplir avec des lignes (peu importe les valeurs pour le moment) contenant les données sous forme "double x ; double y", les données sur 2 colonnes séparées par un point-virgule quoi. Le code donne :
Au niveau du programme principal, la DLL est bien chargée, la fonction est trouvée et est appelée comme suit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 extern "C" __declspec(dllexport) bool __stdcall AddData(TStringList &zob) { zob.Clear(); for (int i = 1 ; i < 101 ; i++) { double gn = (i - 1) * 10.0; double gnn = 100.0 * exp(-gn); zob.Add(FloatToStr(gn) + ";" + FloatToStr(gnn)); } return 1; }
Le typedef sur la fonction importée est défini par :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 AnsiString DLLpath; DLLpath = "Project1.dll"; MainFm->HandleDLL = LoadLibrary(DLLpath.c_str()); if (MainFm->HandleDLL) { MainFm->AddDataOnly = (MYDLLFUNCB)(GetProcAddress(MainFm->HandleDLL , "AddData")); if (MainFm->AddDataOnly) { MainFm->AddDataOnly(*DVHToAdd->ProcessedData); } else ShowMessage("Function not found"); FreeLibrary(MainFm->HandleDLL); } //At this point, ProcessedData should hold the parsed DVH data in the "dose|volume" format int IterLim = DVHToAdd->ProcessedData->Count; for (int k = 0 ; k != IterLim ; k++) { AnsiString TempStr = DVHToAdd->ProcessedData->Strings[k]; char *TempChar = strtok(TempStr.c_str(),",/|;"); DVHToAdd->SeriesDer->AddX(StrToFloat(TempChar)); TempChar = strtok(NULL,",/|;"); DVHToAdd->SeriesDer->YValue[k] = StrToFloat(TempChar); }
Le problème :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 typedef bool (__stdcall *MYDLLFUNCB)(TStringList &zob);
Quand j'exécute pas-à-pas, je vois que la DLL est chargée, la fonction trouvée et que le TStringList revient de l'appel de fonction avec un count à 100 laissant penser que des éléments ont bien été ajoutés sauf qu'aux lignes suivantes, où le programme boucle sur les lignes du TStringList, j'ai une erreur d'accès mémoire. Ca ressemble à une situation où les emplacements mémoire qui contiennent effectivement les lignes rajoutées sont perdus ou ne collent plus au retour de la DLL.
Notez que j'ai essayé avec et sans le rajout aux projets de la librairie Borland pour gestion de mémoire etc. J'ai aussi essayé avec un prototype de fonction où je passe le pointeur vers le TStringList mais les symptômes sont exactement les mêmes.
Ca ne me parait pas particulièrement exotique de faire remplir une liste de chaines par une DLL donc c'est forcément moi qui fait une connerie, laquelle ?
Merci !
Partager