Problem bei Speicherübergabe an DLL

sellerie2001

Grünschnabel
Hi,

ich programmiere unter der MFC an einer DLL, welche Messwerte (die irgendwoher stammen) nach verschiedenen Algorithmen (mit verschiedenen Funktionen) umrechnet. Die einzelnen Funktionen werden über eine Wrapperfunktion mit fester Parameterliste, die innerhalb der DLL, als extern deklariert, implementiert ist. Die DLL und die Wrapperfunktion sind nötig, da nicht nach jedem Zufügen einer neuen Messwertbearbeitungsfunktion, das Hauptprogramm, welches die DLL läd, erneut gelinkt werden muss.

Die Messwerte sind in einer Klasse gespeichert, die sowohl in der Hauptanwendung, als auch in der DLL deklariert und implementiert ist.

Mein Problem ist folgendes:
Ich übergebe die Messwertklassen (variable Anzahl an Klassen mit variabler Anzahl an Messwerten) als Zeiger auf einen Vektor aus void* Elementen (void*, da es verschiedene Messwerttypen in unterschiedlichen Klassen gibt) an die Wrapperfunktion der DLL. Allerdings enthalten die Messwertklassen bei Verwendung in der DLL nur Datenmüll, während sie vorher in der Hauptanwendung einwandfreie Messwerte beeinhalteten.
Es scheint, als ob die DLL den von der Hauptanwendung alloziierten Speicher nicht weiterverwenden kann. Was kann man dagegen tun?

Hauptanwendung:
typedef UINT (CALLBACK* COMHELPER)(DISPID,std::vector<void*>*,const BYTE*, ...);

void rufAuf ()
{
HINSTANCE hInst = LoadLibrary ("Editation.dll");
if (!hInst) return;

COMHELPER pfuncHelper = (COMHELPER) GetProcAddress (hInst, "COMHelper");
if (!pfuncHelper) return;

std::vector<void*>* lpvecMesswerte = GetMesswerte ();

// Z.B.
Messwertklasse *lpMess = (Messwertklasse*) lpvecMesswerte->at (0);
double ldMessDt = lpMess->GetMittelwert (0);
// ldMessDt enthält Werte

pfuncHelper (FUNKTIONSID,lpvecMesswerte,0,NULL);
}


DLL:

EDITATION_API COMHelper (DISPID dispID, std::vector<void*>* pvecValues,
const BYTE* pbParameters, ...)
{
// Z.B.
Messwertklasse *lpMess = (Messwertklasse*) pvecValues->at (0);
double ldMessDt = lpMess->GetMittelwert (0);
// ldMessDt enthält Datenmüll z.B. -2342352
}
 
Ich denke mal dass die DLL nicht auf den Speicher der Anwendung zugreifen kann
vielleicht hilft sowas in der Hauptanwendung(global):
Code:
#pragma data_seg ("shared")
std::vector<void*> lpvecMesswerte;
#pragma data_seg ()
#pragma comment(linker,"/SECTION:shared,RWS")

ansonsten kannst du nicht statt einer std::vector list ein void*-Array übergeben?
 
DLLs können problemlos auf den Speicher der Hauptanwendung zugreifen und umgekehrt. Man muss nur aufpassen, wenn man nicht Multithreaded-DLL als Laufzeitbibliothek eingestellt hat (da die DLL und die Anwendung dann unterschiedliche Heaps haben), und selbst dann ist der einfache Zugriff kein Problem.

Was mir als erstes einfällt:

Stimmt die Funktionsdefinition mit der Funktion haargenau überein?
Ich sehe zum Beispiel in der Hauptanwendung einen Rückgabeparameter mit Typ UINT, im DLL-Code sehe ich da allerdings keinen.

Ansonsten: Debug mal rein. Direkt im Aufruf der DLL-Funktion, stimmen alle Parameter zumindest wertemässig (Pointer-Adressen usw.) oder sind die da schon daneben?
 
Danke für die schnelle Antwort....

Die Funktionsdefinition stimmt schon überein, ich habe die Funktion für diesen Beitrag ein wenig gekürzt um es übersichtlicher zu halten. Dabei habe ich wohl die Deklaration fehlerhaft übernommen ;-(

Das Debuggen ist nicht so einfach:
Obwohl die DLL in einer Debug Version vorliegt, wird vom VisualStudio jeder Haltepunkt ignoriert. Allerdings nur in dieser DLL...alle anderen Dlls meines Projektes funktionieren diesbezüglich einwandfrei. Ich habe schon vieles (natürlich nicht alles) versucht, sie zu debuggen; habe es aber irgendwann aufgegeben...musste es eben mit Messageboxes machen, war zwar stressig, aber funktioniert auch. Dabei fand ich heraus, das alle übergebenen Argumente der Wrapperfunktion die richtigen Werte enthalten. Auch der Vektor ist ein gültiges Objekt mit der richtigen Anzahl an Elementen. Alle Elemente enthalten auch die richtige Anzahl an Messwerten, aber irgendwie sind die Messwerte selbst Murks.
Ich muss dazu sagen, dass ich ein ähnliches Problem bereits hatte:
Die Messung (welche Messwerte erzeugt) ist ein Algorithmus, der in einem Afx-Thread läuft. Auch diesem Thread versuchte ich direkt einen Zeiger auf einen Vektor zu übergeben, aber auch hier entstand Datenmüll. Muss gestehen, dass ich das ganze umgangen habe, indem ich den Vektorzeiger in ein LPARAM gespeichert habe und per SendMessage an den Thread gesendet habe. Das hat funktioniert...ich kann bis jetzt allerdings noch nicht so richtig nachvollziehen, wie Microsofts Message-Handling funktioniert, weshalb ich zu keiner anderen Lösung gekommen bin.
 
Der Vektor ist im MainFrame der Hauptanwendung definiert, Messwertklassenobjekte werden über new erzeugt und per push_back als void* Element gespeichert.

Ich hätte vielleicht noch zufügen sollen, dass die DLL nicht über ihr lib-Datei verwendet wird, sondern nur über irgendeine lokale Funktion eines Dialogs kurzzeitig mit 'LoadLibrary ("Editation.dll") geladen wird, und nach Abschluss der Funktion mit FreeLibrary wieder entladen wird. Vielleicht spielt das ja irgendeine Rolle!?
 
Obwohl es bei der Pointer-Übergabe nicht reinspielen sollte, setze mal bei der DLL und dem Hauptprogramm den Laufzeit-Bibliothek (drecksübersetzerpack)-Typ auf "Multithreaded DLL" (bzw. Multithreaded Debug DLL).

Dann haben DLL und Programm denselben Heap. Die STL erzeugt und zerstört ja andauernd irgendwas, und wenn der eine Heap aufräumen soll, was der andere erzeugt hat... Eigentlich liest du ja in der DLL nur aus, da sollte es eigentlich nicht reinspielen, aber man weiss ja nie.
 
Das (oder etwas ähnliches) scheint funktioniert zu haben. Ich habe einfach alle Methoden in eine neue Multithreaded DLL kopiert und neu übersetzt. Jetzt sind die Werte i.O.
So richtig verstanden, woran es denn gelegen hat, habe ich allerdings nicht, aber hauptsache es funktioniert jetzt. Danke für die Hilfe :-)
 
Zurück