DLL-Erstellung und Calculate bzw. CalculateEx

Antworten
abacom
Site Admin
Beiträge: 3917
Registriert: Dienstag 23. September 2008, 10:54
Kontaktdaten:

DLL-Erstellung und Calculate bzw. CalculateEx

Beitrag von abacom » Dienstag 14. Oktober 2008, 12:06

Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 21.02.2008 14:47 Titel: DLL-Erstellung und Calculate bzw. CalculateEx

--------------------------------------------------------------------------------

Hallo Abacom-Gemeinde,

ich bin mal wieder am Experimentieren mit der neuen CalculateEx-Funktion unter Delphi. Zum Test habe ich eine einfache Umsetzung von arabischen Ziffern in römische Ziffern. Dabei bekomme ich es einfach nicht hin, die Ausgabe des DLL-Bausteines korrekt anzeigen zu lassen. Eine entsprechende (nahezu gleiche) Funktion mit der (alten) Calculate-Funktion reagiert korrekt?!

Ich stehe momentan auf dem sprichwörtlichen Schlauch ...
Falls jemand eine Idee hat ... hier ein kurzer Code-Schnipsel:

Code:
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
var RomanStr : String;
aLongInt : LongInt;
begin
if PInput^[Dec] <> PUser^[Dec_Old] then
begin
PUser^[Dec_Old] := PInput^[Dec];
aLongInt := Round(PInput^[Dec]);
RomanStr := DecimalToRoman(aLongInt);
StrPCopy(PStrings[Roman],RomanStr);
Beep(2000,50);
end;
end;



Das Beep habe ich nur zur Kontrolle gemacht und dieses höre ich auch korrekt in dem PL-Projekt. Allerdings wird als Ausgabe dann nicht der korrekt berechnete Werte (Römische Zahl) dargestellt, sondern die arabische Zahl - also quasi die Eingabe ?!

Setze ich das ganze zum Test mit der alten Calculate-Funktion um, so funktioniert anscheinend alles korrekt:

Code:
Procedure Calculate(PInput,POutput,PUser: PDLLParams);
var RomanStr : String;
aLongInt : LongInt;
begin
if PInput^[Dec] <> PUser^[Dec_Old] then
begin
PUser^[Dec_Old] := PInput^[Dec];
aLongInt := Round(PInput^[Dec]);
RomanStr := DecimalToRoman(aLongInt);
POutput^[Roman] := PInput^[Dec] * 2;
Beep(2000,50);
end;
end;



Ich habe hier einfach nur den Eingang mit 2 multipliziert, es geht ja nur um die Ausgabe des DLL-Bausteins.

Fällt hier jemandem irgendetwas zu ein?

Gruss Stephan

Nach oben


Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 21.02.2008 15:09 Titel:

--------------------------------------------------------------------------------

was landet denn in RomanStr wenn du die Variable im Debugger anguckst?

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 21.02.2008 15:19 Titel:

--------------------------------------------------------------------------------

@Mike D: da ich eine DLL erzeugt habe, läuft der Debugger ja nicht, während ich in PL mein Projekt laufen lasse ... ?? Und übernehme ich den Codeschnipsel in ein eigenständiges Delphi-Programm, so funzt auch alles einwandfrei.

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 21.02.2008 15:27 Titel:

--------------------------------------------------------------------------------

... noch ein kleiner Nachtrag: mir ist grade aufgefallen ... wenn ich die Abfrage am Anfang weglasse
Code:
if PInput^[Dec] <> PUser^[Dec_Old] then

dann funktioniert die Ausgabe einwandfrei ... ?!?
Allerdings wird die Schleife dann natürlich permanent durchlaufen und das ist ja nicht Sinn der Sache ...

Nach oben


abacom
Site Admin


Anmeldungsdatum: 30.06.2006
Beiträge: 898

Verfasst am: 21.02.2008 18:12 Titel:

--------------------------------------------------------------------------------

Nochmals der Hinweis, dass $Pins als erstes Zeichen ein '$' im Namen tragen müssen.

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 22.02.2008 00:07 Titel:

--------------------------------------------------------------------------------

@Abacom: ja - aber doch wohl nur in der Deklaration? ... und dort ist es mit einem $ versehen ...

Nach oben


Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 22.02.2008 19:06 Titel:

--------------------------------------------------------------------------------

Step hat Folgendes geschrieben:
da ich eine DLL erzeugt habe, läuft der Debugger ja nicht,

das der Debugger von Delphi zu blöd ist Breakpoints in DDLs zu finden hatte ich vergessen, bin von LabWindows zu vewöhnt.
Man kann sich aber behelfen, du kannst die Ausführung der DLL in Delphi von Hand auf Pause schalten, dann kommst du zwar nicht in die Proceduren, aber globale Variablen kannst du ansehen. Mach dir eine globale Hilfsvariable und pack das Ergebniss das du beobachten willst in der Procedur da rein.

Mike

PS. TIP: Zum DLL debuggen in Delphi unter Start>Parameter>Host-Anwendung Profilab auswählen. DLL-Projekt compilieren und erzeugen, dann in Delphi starten. Profilab wird automatisch als Host-Anwendung gestartet. Profilab-Projekt laden, vergewissern dass die richtige, neu erzeugte DLL geladen wird, Profilab-Projekt starten.

Nach oben


Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 22.02.2008 19:23 Titel:

--------------------------------------------------------------------------------

es gibt was viel besseres:

OutputDebugString();

http://www.delphipraxis.net/topic47972_ ... eschr.html

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 24.02.2008 22:21 Titel:

--------------------------------------------------------------------------------

@Mike:

danke für die Links. Das sieht sehr interessant aus und werde ich bestimmt demnächst (nach meinem Urlaub ) testen.

Allerdings glaube ich, dass das Problem wo anders liegt - siehe mein oberesPosting/Nachtrag. Wenn ich nur die Abfrage weglasse, läuft alles wie gewünscht und die Schleife wird korrekt durchlaufen (zumindest merke ich das an dem Kontrol-Beep) ...


@abacom:

Nochmal die Frage zur Deklaration: Das '$' als erstes Zeichen gilt doch nur für die Deklaration, oder?
P.S.: In der Hilfe steht noch nicht die Funktion CalculatEx, nur im Delphi-Beispiel im Programmverzeichnis.

Stephan

Nach oben


Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 25.02.2008 00:27 Titel:

--------------------------------------------------------------------------------

CalculateEx steht auch in der Hilfe, da ist das mit dem $ auch etwas deutlicher beschrieben. Der Pinname muss mit $ anfangen

Code:
Function OutputName(Channel: Byte): ShortString; // Return name for each component output pin
begin
// string outputs must be named with leading '$' character!
case Channel of
str_out_1: result:='$_out_1'; //
str_out_2: result:='$_out_2'; //
end;
end;


Mike

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 25.02.2008 10:24 Titel:

--------------------------------------------------------------------------------

@Mike: bei mir in der Hilfe steht zwar die Funktion CalculateEx beschrieben, aber am Ende der Hilfe steht unter dem Punkt:

Zitat:
Siehe auch:
- Beispiel DLL-Quelltext (Delphi)
- Beispiel DLL-Quelltext (C++)
- Grundlagen von Bauteilen



nur die Funktion Calculate! DAS meinte ich mit der Hilfe. Im PL-Programmverzeichnis ist diese Funktion vorhanden. Vielleicht sollte an dieser Stelle die Hilfe auf die neue Funktion aktualisiert werden ...

Aber trotzdem bleibt mein Problem bestehen, in der folgenden Funktion habe ich das erste Zeichen doch mit einem $ besetzt, oder fehlt hier noch was ????

Code:
Function OutputName(Channel: Byte): ShortString; // Return name for each component output pin
begin
case Channel of
Roman : Result := '$Roman'; //
end;
end;



Trotzdem bekomme ich kein entsprechendes Ergebnis als Ausgabe!

Stephan

Nach oben


Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 25.02.2008 15:58 Titel:

--------------------------------------------------------------------------------

so geht es
Code:
var RomanStr : String;

Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
var aLongInt : LongInt;

begin
if (PInput^[Dec] <> PUser^[Dec_Old]) then
begin
PUser^[Dec_Old] := PInput^[Dec];
aLongInt := Round(PInput^[Dec]);
RomanStr := DecimalToRoman(aLongInt);
Beep(2000,50);
end;
StrPCopy(PStrings[Roman],RomanStr);
end;

in der Hilfe steht, das das String-Array für Eingänge und Ausgänge gemeinsam genutzt wird, das heisst vor jedem Aufruf der Procedur werden die Elemente neu mit den Eingangswerten geladen. Daher müssen auch bei jeder Ausführung der Procedure CalculateEx die Ausgangswerte neu gesetzt werden, da sie ja überladen wurden. Damit der String nach der Umwandlung bis zum nächsten Aufruf nicht verloren geht muss die Variable RomanStr global deklariert werden.

@abacom: Ist es richtig, dass die Werte von numerischen Eingängen auch im Stringarray landen, auch wenn die Eingangsnamen kein $ am Anfang haben?

Mike

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 25.02.2008 18:48 Titel:

--------------------------------------------------------------------------------

@Mike: Das ist ja interessant ... wenn man allerdings die Variable in der DLL global deklariert, kann man die DLL unter dem gleichen Namen nur einmal verwenden (s. Hilfe).

@Abacom: Es wäre wünschenswert, wenn ein diesbezüglicher Hinweis in der Hilfe auftauchen würde, vor allem weil die Vorgehensweise bei CalculateEx ja wohl NICHT analog zur "alten" Calculate-Funktion läuft ...

Stephan

Nach oben


Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 25.02.2008 21:20 Titel:

--------------------------------------------------------------------------------

dann machs doch so
Code:
var RomanStr : Array [1..5] of String;

Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
var aLongInt : LongInt;
aIndex : Integer;
begin
aIndex := Round(PUser^[DLLIndex]);
if (PInput^[Dec] <> PUser^[Dec_Old]) then
begin
PUser^[Dec_Old] := PInput^[Dec];
aLongInt := Round(PInput^[Dec]);
RomanStr[aIndex] := DecimalToRoman(aLongInt);
Beep(2000,50);
// POutput^[Index] := PUser^[DLLIndex];
end;
StrPCopy(PStrings[Roman],RomanStr[aIndex]);
end;


oder pack den ascii-code der Zeichen in PUser

Mike

Nach oben


Step



Anmeldungsdatum: 30.01.2007
Beiträge: 67

Verfasst am: 26.02.2008 10:48 Titel:

--------------------------------------------------------------------------------

Danke nochmal an Mike für die "Versuche"!

Abschließend noch der Hinweis, dass die Funktion nur dann richtig funktioniert, wenn diese Übergabe des Strings AUSSERHALB des Vergleiches steht (-> if (PInput .... usw.):

Code:
StrPCopy(PStrings[Roman],RomanStr[aIndex]);



so wie Mike meinen ursprünglichen Source verändert hat (warum das so ist, bleibt mir noch rätselhaft - aber egal ... ).

Stephan

----------------------------------------------------------------------------------------

Mike D



Anmeldungsdatum: 03.07.2006
Beiträge: 236

Verfasst am: 27.02.2008 09:32 Titel:

--------------------------------------------------------------------------------

Step hat Folgendes geschrieben:
(warum das so ist, bleibt mir noch rätselhaft - aber egal ... ).

Mike D hat Folgendes geschrieben:
in der Hilfe steht, das das String-Array für Eingänge und Ausgänge gemeinsam genutzt wird, das heisst vor jedem Aufruf der Procedur werden die Elemente neu mit den Eingangswerten geladen. Daher müssen auch bei jeder Ausführung der Procedure CalculateEx die Ausgangswerte neu gesetzt werden, da sie ja überladen wurden.


bei jedem Wechsel des Eingangswertes hat deine Version auch funktioniert, nur wurde der String bei der nächsten Runde sofort wieder überschrieben.

Mike
ABACOM support

Antworten

Zurück zu „DLL-Programmierung“