Frage zu DLLs / Objekten und ihrer Gültigkeit.
-
Wie meinst du das @Hustbaer?
Du kannst aus einer DLL locker einen UINT_PTR oder einen void* oder sonstwas rausgeben damit der Aufrufer sich den merkt, und den dann an anderer Stelle vom Aufrufer wieder entgegennehmen, casten, dereferenzieren, fertig. Alles kein Problem. Probleme könnte es geben wenn du auf einer Seite (DLL) new/malloc machen willst und auf der anderen Seite (EXE) delete/free - aber so wie ich das verstehe muss das ja in deinem Fall nicht gehen.
Von mir aus kann das delete auch in der DLL passieren. Aber sobald ich eine Funktion verlasse räumt Halcon schon freudig auf. Sprich sobald ich UINT_PTR oder void* oder so rausgeb und die Funktion verlass, ist das Objekt im Nirvana... OBWOHL eine, wenn auch anderen Typs, Variable existiert.
Ich müsste also die Ursprungsvariable. also das Objekt irgendwie innerhalb der DLL am Leben halten... Und das kann ich nicht lösen. Da brauche ich dringend Hilfe. Irgendwo hängts da bei mir.
Mein eines Beispiel stammt aus einem von mir erstellten Visual Studio Konsolenprogramm. EInfach mal zum Testen. HImage ist eine Halcon Klasse, die ein Bild beinhaltet.
Ich werfe also eine Funktion an, die mit new ein solches Bild erzeugt. Caste dessen ADresse auf ein INT64. (Halcon arbeitet schon mit 64er Adressierung...
Gebe dieses INT64 mit return zurück. Rufe in der nächsten Zeile eine Funktion auf und gebe ihr das INT64. In dieser Funktion caste ich INT64 wieder als Pointer auf ein HImage. Die Adresse existiert noch. Aber das Bild ist schon aufgeräumt an dieser stelle.
Der gleiche Code mit irgend einem sTL Zeiger... Geht...
Wie löse ich sowas nun innerhalb einer DLL, daß der allokierte Speicher am Leben bleibt...
Deswegen meine Frage mit der Klasse innerhalb der DLL. Wenn ich doch nun eine Klasse habe, mit HImage* m_bild; als private. Im Konstruktor new. Im Destruktor delete.
Und ich nun die Klasse exportiere...... Geht das nun ohne die Halcon Header nochmal in Borland einzubinden (Was ja ned geht)? Aufruf der Klasse ist ja ohne Typen... Nur die Klasse... Die Halcon Typen sind ja in der DLL gekapselt.
Ich werde auf kurz oder lang auf VS umsteigen müssen. Denn da kommen noch Kameratreiber dazu. CAN Treiber etc. Ich hab noch keine gesehen, die auf Borland zugeschnitten waren... Evtl. versuche ich aber dann möglichst plattformunabhängig zu arbeiten. Sprich Boost und wxwidgets oder so statt MFC.
-
OK. Sorry falls dich das jetzt ärgern sollte was ich gleich schreibe, aber naja.
Wie kommst du überhaupt auf die Idee dass diese Halcon Garbage Collection verwendet?
Ich kenne keine Möglichkeit in einem C++ Programm ohne Compilerunterstützung einen INT64 von einem Zeiger unterscheiden zu können. Soll heissen: selbst WENN die Halcon Garbage Collection verwendet müsste diese konservativ sein, und als solche den INT64 für einen "möglicherweise-gültigen-Zeiger" ansehen, und müsste das Objekt stehen lassen. Die "DLL-Grenze" spielt dabei überhaupt keine Rolle. Mir wäre auch keine C++ Library bekannt die soetwas macht, ausser eben spezielle Garbage Collection Libraries die eben Garbage Collection und sonst nix implementieren.Nochwas: die Halcon kann nicht mit 64 Bit Zeigern arbeiten wenn die Plattform nur 32 Bit Zeiger verwendet. Wenn du also ein 64 bittiges Windows und einen 64 Bit Compiler verwendest sind alle deine Zeiger 64 Bit (nicht nur die der Halcon), wenn du ein normales 32 bittiges Windows oder einen 32 Bit Compiler verwendest sind alle deine Zeiger 32 Bit.
Ich vermute das Problem liegt woanders.
Hast du das Bild denn schon einmal im VC Code inspiziert bevor die DLL verlassen wird? Ist es da OK? Hast du schonmal die Zeigerwerte vor dem "rausreichen" und nach dem "reinbekommen" ins Debug-Out geschrieben?
Verwendest du mehrere Threads? Bist du sicher dass das Problem nicht daher kommen kann?Oder hast du denn überhaupt schon versucht ob es denn einen Unterschied macht wenn du den Zeiger in der DLL in einer globalen Variable speicherst?
----
Im Übrigen wäre es wohl besser wenn du Code postest der wirklich so vorkommt, und nicht etwas zusammengeschustertes was sich nichtmal compilieren lässt. Ne void Funktion die einen Integer zurückgibt... sicher nicht.
-
hustbaer schrieb:
OK. Sorry falls dich das jetzt ärgern sollte was ich gleich schreibe, aber naja.
Wie kommst du überhaupt auf die Idee dass diese Halcon Garbage Collection verwendet?
Ich kenne keine Möglichkeit in einem C++ Programm ohne Compilerunterstützung einen INT64 von einem Zeiger unterscheiden zu können. Soll heissen: selbst WENN die Halcon Garbage Collection verwendet müsste diese konservativ sein, und als solche den INT64 für einen "möglicherweise-gültigen-Zeiger" ansehen, und müsste das Objekt stehen lassen. Die "DLL-Grenze" spielt dabei überhaupt keine Rolle. Mir wäre auch keine C++ Library bekannt die soetwas macht, ausser eben spezielle Garbage Collection Libraries die eben Garbage Collection und sonst nix implementieren.DAs Bild ist VOR der Übergabe ok. NACH der Übergabe ist der Inhalt im Eimer.
Nochwas: die Halcon kann nicht mit 64 Bit Zeigern arbeiten wenn die Plattform nur 32 Bit Zeiger verwendet. Wenn du also ein 64 bittiges Windows und einen 64 Bit Compiler verwendest sind alle deine Zeiger 64 Bit (nicht nur die der Halcon), wenn du ein normales 32 bittiges Windows oder einen 32 Bit Compiler verwendest sind alle deine Zeiger 32 Bit.
Ok was ist dann __w64 (Compiler #Option für 64 bit Systeme) und wieso beschwert sich VS wenn ich die Zeiger auf int32 caste, daß ich den Zeiger beschneide mit einer Warnung.
Ich vermute das Problem liegt woanders.
Hast du das Bild denn schon einmal im VC Code inspiziert bevor die DLL verlassen wird? Ist es da OK? Hast du schonmal die Zeigerwerte vor dem "rausreichen" und nach dem "reinbekommen" ins Debug-Out geschrieben?
Verwendest du mehrere Threads? Bist du sicher dass das Problem nicht daher kommen kann?Oder hast du denn überhaupt schon versucht ob es denn einen Unterschied macht wenn du den Zeiger in der DLL in einer globalen Variable speicherst?
Ja, Nein, Nein, Ja definitiv.
Zur Aufklärung: DLL technisch habe ich noch nichts. Meine Versuche mache ich in einem prozeduralen Konsolenprogramm unter VS. Ich will da nicht zuviel Zeit investieren eine DLL zu bauen, bevor ich weiß wie ichs anzustellen habe. Deswegen überhaupt der Thread.
Im Übrigen wäre es wohl besser wenn du Code postest der wirklich so vorkommt, und nicht etwas zusammengeschustertes was sich nichtmal compilieren lässt. Ne void Funktion die einen Integer zurückgibt... sicher nicht.
Ok hast du mal eben 7000€ etwa über für eine Developer Lizens? Dann gebe ich dir gerne laufenden Code. Meinst du ich mach hier aus Langeweile abstrakte Beispiele? Und es tut mir ja leid, daß ich nach 19 Stunden auf Arbeit und nachts um 12 einen kleinen Tippfehler einbaue *grrrr*
-
Und wenn du das Objekt HImage in deinem Hauptprogramm erstellst und nur dessen Zeiger an die DLL übergibst? Dann kannst du in der DLL machen was du willst, der Garbage Collector sollte das Objekt nicht zerstören.
-
HImage --> Include "Halcon.cpp" -->Unresolved Externals --> BCB Inkompatibilität --> Genau das was ich umgehen muss
-
__w64 heisst in dem Fall nicht dass der Zeiger 64 Bit gross ist. Lies es bitte in der MSDN nach wenn du es mir nicht glaubst.
Ich will da nicht zuviel Zeit investieren eine DLL zu bauen, bevor ich weiß wie ichs anzustellen habe.
Ok, verstehe ich.
Ok hast du mal eben 7000€ etwa über für eine Developer Lizens?
Willst du mich verarschen oder willst du (meine) Hilfe?
Dann gebe ich dir gerne laufenden Code. Meinst du ich mach hier aus Langeweile abstrakte Beispiele?
Was weiss ich?
Bloss bringen deine abstrakten Beispiele IMO genau nichts, da ich mir ziemlich sicher bin dass sie den Fehler den du suchst "maskieren". Ich will ja nicht ein riesen Programm welches ich kompilieren kann + Libraries, aber ich erwarte mir dass du ein kleines Testprogramm schreibst wo das besagte Problem auftritt, und dann den Code den DU geschrieben hast (und den du daher auch posten darfst) 1:1 mittels copy & paste hier postest. Genau das KANNST du nicht gemacht haben, da der Code den du gepostet hast nichmal kompilieren könnte, wegen besagtem Fehler.
Irgendwie nervt es auch etwas dass du hier (falsche) Vermutungen anstellst und diese als Tatsachen formulierst (z.B. "Halcon arbeitet schon mit 64er Adressierung") - und hilfreich ist es ganz sicher auch nicht.
-
con capisce un tubo...
Wenn du nicht ständig versuchen würdest mich anzumachen wäre es eine Ecke einfacher.
Nochmal: Ein LAUFENDES Beispiel für Halcon kann ich dir nicht geben, da die Typen zu Halcon gehören und du dafür eine Developer Lizens brauchst, da sonst
die DLLs nicht laufen.CPP eines dyn dll Projekts in Borland.
int* foo; extern "C" _declspec(dllexport) void Anlegen() { foo = new int(); *foo = 9969; } extern "C" _declspec(dllexport) int Auslesen() { return (int) foo; }Holzhammermethode. Prozeduraler Code, Dll daraus gebaut.
Erzeugt, kopiert, Konsolenprogramm aufgemacht.
HINSTANCE hdll; hdll = LoadLibrary("Lan_German.dll"); typedef void (*Anlegen)(); typedef int (*Auslesen)(); Anlegen anleg; Auslesen ausles; anleg= (Anlegen) GetProcAddress (hdll, "_Anlegen"); ausles= (Auslesen) GetProcAddress (hdll, "_Auslesen"); anleg(); int* p = (int*)ausles();Inhalt p ->9969. Wird also zwischen den Aufrufen der DLL Funktion nicht gelöscht. Sowas wollte ich wissen... Jetzt habe ich mir halt doch die Zeit aus den Fingern gesaugt, die ich nicht habe.
Visual Studio. Konsolenprogramm
#include "stdafx.h" #include "HalconCpp.h" #include <iostream> #include <vector> INT64 action() { using namespace std; using namespace Halcon; //int width = 10; // int height = 10; HWindow hWindow(""); HTuple OpSys; get_system("operating_system",&OpSys); HTuple Pointer, Type, Width, Height, WindowHandle, WindowHandle1; HTuple Pointer1, Type1, Width1, Height1, WindowHandle2; HTuple HorProjection, VertProjection; Hobject QImage,EImage, Rectangle, Rectangle1, ImageMean, Rect, Result; Hobject RectangleResult; WORD* quellbild; char* qtype=new char(10); Hlong qwidth=0; Hlong qheight=0; WORD* ergbild; char* etype=new char(10); Hlong ewidth=0; Hlong eheight=0; //Generieren des Quellbilds INT64 adresse =(INT64) &QImage; Hobject* neuesbild; neuesbild = (Hobject* ) adresse; gen_image_const(neuesbild,"uint2",100,100); return adresse; } void speichern(INT64 puffer) { using namespace Halcon; Hobject* ergimage = (Hobject*) puffer; //BANG Bild existiert gar nicht write_image(*ergimage, "png fastest",0,"C:\\test"); } int _tmain(int argc, _TCHAR* argv[]) { using namespace Halcon; set_system("do_low_error","false"); INT64 bild = action(); Hobject* ergimage = (Hobject*) bild; //BANG hier krachts eigentlich schon write_image(*ergimage, "png fastest",0,"C:\\test"); speichern(bild); return 0; }Bei write_image krachts. Egal welches der beiden ich aktiv habe.
Was mir nach genug Schlaf aufgefallen ist, ist daß es eventuell daran liegt, daß die Variablen nur in den Funktionen gültig sind, mein foo in der dll global.
Die Kombination aus beiden Programmen muss das ERgebnis werden... Ausserhalb der DLL darf KEINERLEI Halcon auftauchen. Nur normale C/C++ Typen. DEswegen der Umweg über das Casten.
-
ich weis jetzt nicht ob das auch ein schreibfehler ist. aber ersetzte mal diese Zeile hier
Hobject QImage,EImage, Rectangle, Rectangle1, ImageMean, Rect, Result;durch diese hier:
Hobject EImage, Rectangle, Rectangle1, ImageMean, Rect, Result; Hobject* QImage = new Hobject;In deinem Beispiel legst du nämlich wirklcih nur eine lokale Variable QImage vom Typ Hobject an. Die wird dann beim verlassen der Funktion gelöscht.
Mit dem hier:
INT64 adresse =(INT64) &QImage; Hobject* neuesbild; neuesbild = (Hobject* ) adresse;konvertierstu du wirklich nur die Adresse des (lokalen Objektes) QImage nach INT64 und dann wieder nach Hobject*.
-
Fuck... (Wieso konvertiert das Forum Fu... in Love? LOL?)
Du hast Recht. Das kommt davon wenn man sowas mit nem Kollegen nebendran schreibt, der nicht wirklich C++ programmiert und mit dem diskutiert.Ok. Danke Chris! Das dürfte es gewesen sein. Wenn mein Dongle nachher wieder kommt probier ich das aus. Daran hab ich überhaupt nicht gedacht.
QImage ist lokal und ich jongliere nur die Adresse durch die Gegend.
-
Siehste, genau deswegen wollte ich kein für's Forum gettipseltes Beispiel sondern Copy & Paste

Und... wie gesagt ich bin mir sicher dass die Halcon keine Garbage Collection macht, d.h. du solltest die Objekte auch löschen (in der DLL, mit delete, sollte klar sein), sonst musst du mit Memory Leaks rechnen.
Und weil's zum Guten Stil gehört änder doch deine INT64 einfach noch in "void*" - dadurch ist dann auch automatisch egal ob es 64 Bit oder 32 Bit Zeiger sind. Und mit "void*" sollte der Borland schon klarkommen, und das 'extern "C"' macht auch kein Problem (weiss ich aus eigener Erfahrung, selbst schon gemacht).
Wichtig ist wie gesagt dass du alles was du mit Code in der DLL anlegst auch wieder mit Code in der DLL löscht, sonst wird's krachen, da der MSVC und der Borland nicht den selben Heap verwenden. Solange es alles Halcon Objekte sind die du per INT64/void* rumreichst geht es sowieso nicht anders, bloss falls du irgendwo new char[] oder malloc verwendest eben der Hinweis: alles dort freigeben wo es angefordert wurde.
Noch ein Tip (sollte klar sein, bloss zur Sicherheit): du solltest aus deiner DLL keine Exceptions rauswerfen, das wird der Borland u.U. auch nicht mögen. Also überall wo was knallen könnte einen try{}catch(...){} rummachen und den Fehler dann über den Returnwert "weiterleiten".