Autor Beitrag
Gewuerzgurke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Sa 12.09.09 17:15 
Hallo,
hier erstmal ein Codeschnipsel:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure test;
var
 DieVariable : string;
begin
 DieVariable := 'Normal';
 ShowMessage(DieVariable);     // das erste ShowMessage
 InDll(DieVariable);
 ShowMessage(DieVariable);     // das zweite ShowMessage
 FunktionPlatzhalter;
 FunktionPlatzhalter;
 FunktionPlatzhalter;
end;

Die procedure InDll steht (Wie der Name schon sagt) in einer DLL und wird dynamisch geladen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure InDll(out Wert : string);
begin
 Wert := 'Geaendert';
end;
exports InDll;

Durch das out wird (Wenn ich das richtig verstanden habe) die Variable außerhalb "bearbeitet". Tatsächlich zeigt das erste ShowMessage Normal und das zweite Geaendert. Am Ende der procedure test (NACH den Platzhalter-Funktionen, die ich mal schematisch eingefügt habe) kommt aber eine Zugriffsverletzung. Ich kann in meinem Fall nicht oder nur sehr schwer mit Pointern arbeiten und komme nicht dahinter woher die Zugriffsverletzung kommt. Was kann man da machen?
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: Sa 12.09.09 17:28 
hast Du Sharemem eingebunden, wie es im Kommentar steht, den man automatisch im DPR file hat, wenn man eine neue DLL anlegt ? Sonst hast Du Probleme mit Strings von und zu DLLs

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Sa 12.09.09 19:17 
Hm, in meinem richtigen Programm hatte ich eigentlich keine Strings "verschickt", trotzdem kommt der Fehler jetzt nur noch beim beenden des Programms...
Das bekomme ich schon noch hin.

Vielen Dank erstmal. :D
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 13.09.09 01:25 
Also nur mal so zum Klarstellen : Wenn Du hier Code ablieferst, der garnicht der Code ist, den Du benutzt und wir sollen da in diesem Code die Fehler suchen, die Dein anderer Code produziert, dann rechne in Zukunft nicht mehr mit meiner Hilfe :evil: *sauer ist*

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 13.09.09 02:13 
user profile iconGewuerzgurke hat folgendes geschrieben Zum zitierten Posting springen:
Hm, in meinem richtigen Programm hatte ich eigentlich keine Strings "verschickt", trotzdem kommt der Fehler jetzt nur noch beim beenden des Programms...
Das bekomme ich schon noch hin.

Und wie sollen wir dir jetzt helfen, wenn du uns nicht den Code zeigst, um den es geht? Wenn mein Auto kaputt ist, hilft es der Autowerkstatt auch recht wenig, wenn ich dort das Auto meiner Freundin abgebe. :roll:
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: So 13.09.09 09:40 
Die Verwendung von AnsiString zwischen EXE und DLL ist etwas problematisch. Da Delphi die Speicherreservierung selber vornimmt.
Also überschneiden sich EXE und DLL. Daher sollte man auch die Sharemem einsetzen. Hat den Nachteil, das du die borlndmm.dll bei
der Weitergabe mit geben musst.

Entweder du machst die Speicherreservierung selber oder du überlässt es Windows. In dem du WideString benutzt.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
library MyLib;

procedure InDll(out MyString: WideString); safecall;
begin
  MyString := 'Geändert';
end;

exports
  InDll;

begin
end.


Andere Möglichkeit wäre noch über einen eigenen Speichermanager.


Ein ganz wichtiger Hinweis kam aber schon von Delphi, den du wohl übersehen hast, als du das DLL Projekt gestartet hast:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
{ Wichtiger Hinweis zur DLL-Speicherverwaltung: ShareMem muss sich in der
  ersten Unit der unit-Klausel der Bibliothek und des Projekts befinden (Projekt-
  Quelltext anzeigen), falls die DLL Prozeduren oder Funktionen exportiert, die
  Strings als Parameter oder Funktionsergebnisse übergeben. Das gilt für alle
  Strings, die von oder an die DLL übergeben werden -- sogar für diejenigen, die
  sich in Records und Klassen befinden. Sharemem ist die Schnittstellen-Unit zur
  Verwaltungs-DLL für gemeinsame Speicherzugriffe, BORLNDMM.DLL.
  Um die Verwendung von BORLNDMM.DLL zu vermeiden, können Sie String-
  Informationen als PChar- oder ShortString-Parameter übergeben. }

_________________
Ciao, Sprint.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 13.09.09 09:43 
Wie er schon gesagt hat: Es ging ihm gar nicht um Strings, er hat nur irgendwas einfach so gepostet statt dem echten Quelltext...
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: So 13.09.09 10:47 
Der Quelltext da oben ist aus einem kleinen Testprogramm, dass ich extra zum lokalisieren des Problems geschrieben habe.

In meinem richtigen Programm wird statt einem String ein IDirect3DDevice9 (Was vermutlich auch Strings enthält) übergeben. Wenn ich da mit Pointern arbeiten würde, währe ich wieder an dem Problem, eine Variable/Funktion innerhalb einer Klasse über einen Pointer zu finden - so ähnlich wie hier: www.delphi-forum.de/viewtopic.php?t=93369 (Ja, ich arbeite immer noch an meinem Programm mit den Objekten und Records).

Mit GetProcAddress würde das vermutlich gehen aber dann ist die Performance weg.

Gut, dank Sharemem habe ich das jetzt (fast, bis auf den Fehler am Ende) gelöst.

Ich wollte den Quelltext mit IDirect3DDevice9 nicht posten, weil der groß und unüberschaubar ist - eben typisch DirectX...

[EDIT:] Oh, mein 100ster Beitrag!
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 13.09.09 16:57 
Falls das Direct3D zeugs zufällig aus einer Komponentensammlung kommt, dann link mal die Pakete dynamisch, ansonsten haben exe und DLL eigene Kopien und das kann zu Fehlern führen..

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Mo 14.09.09 17:15 
Wie meinst du das "Exe und Dll haben eigene Kopien"? Heist das, ich muss die DLLs für DirectX auch dynamisch laden?

Der Fehler am Programmende kommt übrigens von ShareMem. Auch wenn ich die DLLs weglasse und nur ShareMem einbinde kommt am Ende ein Fehler :shock: . Außerdem habe ich gelesen, dass man mit ShareMem immer eine ShareMem.dll mitgeben muss, kann diese aber nirgendwo finden.

Sharemem soll außerdem sehr langsam sein - was in meinem Fall ärgerlich währe. Ich habe schon überlegt, etwas anderes statt ShareMem zu verwenden, was die Sache aber nicht unerheblich verkomplizieren würde...
Wie groß ist denn der Performance-Verlust von ShareMem?

Außerdem verstehe ich nicht, warum die Strings überhaupt problematisch sind, wenn ich out verwende...
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Mo 14.09.09 20:10 
user profile iconGewuerzgurke hat folgendes geschrieben Zum zitierten Posting springen:
Der Fehler am Programmende kommt übrigens von ShareMem. Auch wenn ich die DLLs weglasse und nur ShareMem einbinde kommt am Ende ein Fehler

Hast du ShareMem als erste Unit in der DPR eingetragen?

Zitat:
Außerdem habe ich gelesen, dass man mit ShareMem immer eine ShareMem.dll mitgeben muss, kann diese aber nirgendwo finden.

borlndmm.dll

Zitat:
Ich habe schon überlegt, etwas anderes statt ShareMem zu verwenden, was die Sache aber nicht unerheblich verkomplizieren würde...

Es gibt ja einige Alternativen. Selber würde ich ShareMem auch nicht nutzen.

Zitat:
Außerdem verstehe ich nicht, warum die Strings überhaupt problematisch sind, wenn ich out verwende...

Weil deine EXE und deine DLL einen MemoryManager haben. Also in einem Programm zwei. Beide versuchen dann den AnsiString zu verwalten.

Wo es dann zu Problemen kommen kann. Bei WideString übernimmt Windows die Verwaltung.
Und bei der Nutzung von ShareMem bzw. deren Alternativen übernehmen die dann die Speicherverwaltung.
Darum muss die Unit auch an erster Stelle in deiner DPR stehen.

Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Moderiert von user profile iconSprint: Benötigte Zeilenumbrüche/Leerzeilen hinzugefügt.

_________________
Ciao, Sprint.


Zuletzt bearbeitet von Sprint am Di 15.09.09 13:40, insgesamt 1-mal bearbeitet
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Mo 14.09.09 21:12 
Ich hatte es als zweites eingetragen... Zu blöd aber auch. Jetzt, wo (<-- Umgangssprache :mrgreen:) ich es überall als erstes eingetragen habe, geht's. :D

Die borlndmm.dll habe ich im Bin von Delphi gefunden - muss ich die jetzt immer im gleichen Ordner wie mein Programm mitgeben, wenn das andere System kein Delphi hat?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 14.09.09 21:47 
user profile iconGewuerzgurke hat folgendes geschrieben Zum zitierten Posting springen:
Die borlndmm.dll habe ich im Bin von Delphi gefunden - muss ich die jetzt immer im gleichen Ordner wie mein Programm mitgeben, wenn das andere System kein Delphi hat?
Richtig. ;-)
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Mo 14.09.09 22:27 
Och nö! Das zerstört mir das ganze Panorama :mrgreen:

Wenn ich die DLL in einen Unterordner schieben wollte, müsste ich vermutlich die ShareMem.pas anpassen - und die ist nur als .dcu vorhanden und vermutlich urheberrechtlich geschützt...

Ich glaub' ich versuch's doch mal mit den Alternativen.
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Do 17.09.09 22:41 
Jetzt muss ich doch noch mal fragen, ob es nicht eine Möglichkeit gibt, die DLL doch in einen Unterordner zu schieben. Ich muss ja für DirectX sowieso schon welche mitliefern.

Ich meine in Delphi liegt sie ja auch in einem anderen Ordner. Stellt man so was über die Registy ein?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 18.09.09 02:35 
Die DLL muss von Windows gefunden werden, also im PATH liegen. Die kann auch in ein Unterverzeichnis gelegt werden, wenn dieses dem PATH hinzugefügt wird oder theoretisch auch ins System32-Verzeichnis gelegt werden (wobei bei letzterem eine Warnung notwendig wäre, dass ggf. andere Programme beeinträchtigt werden durch dein Programm). Beides hat aber einige Nachteile. Zum Beispiel, dass man das Programm nicht mehr einfach in ein anderes Verzeichnis schieben kann bzw. dass man ggf. Versionskonflikte mit den DLLs bekommt.

Deshalb würde ich das lieber in das Verzeichnis der Exe legen (wie es Microsoft auch empfiehlt) statt da zusätzliche Verrenkungen machen zu müssen. Möglich ist es natürlich auch wie oben gesagt, vorausgesetzt du benutzt ein Setup.
Gewuerzgurke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 152

Win XP
Lazarus
BeitragVerfasst: Fr 18.09.09 14:44 
Achso. Naja, dann sind halt da ein Paar DLLs mit im Verzeichnis. Ich kann sie ja noch verstecken, dann sollte es nicht weiter stören.