Vergleich "FPC" mit "C"

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Hallo,

ich habe hier mal zwei kleine Quelltexte, einen in FPC den anderen in C. Beides sollen dll für Scilab werden. Der C-Quelltext funktioniert, der FPC nicht.
FPC:

Code: Alles auswählen

library sequenz;
procedure sequen(var ein: integer; var aus: array of integer); cdecl;
var i: integer;
begin
   for i:=0 to ein do aus[i]:=i;
end;
exports
   sequen;
begin
end.
Der C-Text:

Code: Alles auswählen

void sequen(int *in, int *out)
{
	for(int i=0; i<*in; i++)
	out[i]=i;
}
Die FPC-DLL funktioniert in Scilab, d.h. Scilab stürzt beim Aufruf nicht ab, aber es werden statt der Zahlenwerte die Adressen der Werte ausgegeben.
Wenn "ein" bzw. "in" z.B. 5 ist, dann soll: 0 1 2 3 4 herauskommen. Es kommen aber fünf Zahlen dieser Güte "65553" heraus.

Die Übergabe einer Variablen "call by Reference" also mit "var aus: integer" sollte doch dem "int *out" entsprechen. Nur C ist es wohl egal ob "out" später ein Array wird oder nicht.
FPC moserte bei "var aus: integer", weil "aus" später indiziert angesprochen wird, wollte er "var aus: array of integer".

Es sieht so aus als würden in meinem Array "aus" nicht die Zahlenwerte von "i" sondern die Adressen gespeichert.

Wo liegt mein Fehler?

Vielen Dank für Eure Hilfe

Volker

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Vergleich "FPC" mit "C"

Beitrag von RSE »

Koorekt sieht der Quelltext so aus:

Code: Alles auswählen

library sequenz;
 
procedure sequen(const ein: integer; out aus: array of integer); cdecl; // <<< const bzw. out würde da vollkommen ausreichen, aber das Interface ist ja von SciLab festgelegt...
var
  i: integer;
begin
  SetLength(aus,ein); // <<<
  for i:=0 to ein-1 do // <<< nur bis ein-1!
    aus[i]:=i;
end;
 
exports
  sequen;
 
begin
end.
Edit: Der Open Array Parameter ist glaube ich nicht die richtige Entsprechung für das, was ein C-Programm da erwartet. Da musst du wohl glaube ich einen nullterminierten "String" von Werten übergeben... Also mit GetMEM oder so selbst entsprechend Speicher reservieren und mit einem entsprechenden Nullwert abschließen. Da kann ich aber nicht genauer helfen, wie der Bitstring zum Schluss aussehen muss, damit C das versteht, ich kann kein C ;-)
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Vergleich "FPC" mit "C"

Beitrag von theo »

Ich würde da immer nah am Original bleiben. Die Pointer Akrobatik ist ja auch in FPC möglich:

Code: Alles auswählen

procedure sequen(_in: Pinteger; _out:Pinteger);
var i:integer;
begin
  for i:=0 to _in^-1 do _out[i]:=i;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var pint:PInteger;
int:integer;
begin
 int:=3;
 pint:=GetMem((int)*SizeOf(Integer));
 sequen(@int,pint);
 caption:=inttostr(pint[0])+' '+inttostr(pint[1])+' '+inttostr(pint[2]);
 FreeMem(pint);
end;
Bin nicht 100% sicher ob es da keine Einwände gibt, aber es funzt und kackt nicht ab. ;-)

TIntegerArray oder PIntegerArray wäre wahrsch. auch möglich.

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Vergleich "FPC" mit "C"

Beitrag von RSE »

Du hast recht, wenn der C-Quelltext so funktioniert, muss ja der Speicher schon reserviert sein...

Und Modifier sollte man wohl ebenso weglassen, wenn ich mir die Doku so ansehe, zumindest const scheint da sehr speziell zu sein:

When parameters are declared as value parameters, the procedure gets a copy of the parameters that the calling statement passes. // by value
var: When parameters are declared as variable parameters, the procedure or function accesses immediatly the variable that the calling block passed in its parameter list. // by reference
out: The purpose of an out parameter is to pass values back to the calling routine: The variable is passed by reference.
const: A constant argument is passed by reference if its size is larger than a pointer. It is passed by value if the size is equal or is less then the size of a native pointer.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Vergleich "FPC" mit "C"

Beitrag von marcov »

Theo hat recht. Denke das sogenannte "Open Arrays" auch den Anzahl Elementen durchgeben. (aber vielleicht nicht wenn CDECL;, aber das sollte man dann aber unbedingt kontrollieren, und dann noch würde ich für die Pointer Lösung gehen )

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Hallo zusammen,

tschuldigung, bin erst gestern spät zum Ausprobieren gekommen, aber es funktioniert nicht.

@theo: Mit den PInteger Open arrays kommt das Gleiche raus wie bei der Übergabe mit var.
Ergebnis anstelle 0 1 2 3 4 kommen diese Zahlen: 65536. 196610. 6.737D+08 6.737D+08 6.737D+08

@RSE: Bei Deinem Lösungsvorschlag meckert der Compiler über die Variable "aus". Er will nach dem out den Doppelpunkt.
Lasse ich "aus" weg und ersetzte es natürlich auch in der Schleife gegen out dann kommen diese Zahlen:
65536. 196610. 327684. 458758. 589832

Aber zumindest stürzt Scilab nicht ab.

Trotzdem Danke für die Hilfe!!!!!!!!!!!!

Gruß

Volker

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Vergleich "FPC" mit "C"

Beitrag von RSE »

Wenn er out nicht kennt, dann stimmt was nicht. Bitte poste mal deine Lazarus- und FPC-Versionen und deine komplette Unit/Library

Edit: Die Implementierung von theo entspricht 1:1 der C-Implementierung. Wenn die nicht funktioniert, dann liegt es nicht am Quelltext. Wo hast du den C-Quelltext her? Bist du sicher, dass der 100% läuft und die Speicherreservierung tatsächlich vor dem Funktionsaufruf passiert? Bitte vergiss meine Implementierung, die von theo ist richtig.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: Vergleich "FPC" mit "C"

Beitrag von Hitman »

Bei den Werten die da rauskommen sieht das danach aus, als erwartet er 16bit Integer! (Sprich: SmallInt)
(1 << 16) + 0 = 65536
(3 << 16) + 2 = 196610
Der Rest dürfte folglich Garbage sein.

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Vergleich "FPC" mit "C"

Beitrag von RSE »

Hitman, das wäre auch mein nächster Verdacht gewesen ;-)
In Code ausgedrückt wäre das dann:

Code: Alles auswählen

procedure sequen(_in: ^Smallint; _out:^Smallint);
var i:integer;
begin
  for i:=0 to _in^-1 do _out[i]:=i;
end;
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Der C-Quellcode funzt 100%ig. Den habe ich aus einem Tutorial (pdf, ca. 15 Seiten). Da beschreibt jemand wie man C++ dll's mit VC, C++Builder und DevC++ erstellt.
Da geht's recht umfangreich zur Sache. Man muß da mit irgendeiner TChang-Pe software in die dll reingehen und diverses herauslöschen.

Ich hab' einfach den beschriebenen Quelltext herausgenommen und mit dem LCC-Compiler über scilab compiliert.
Der Scilab-Befehl lautet: ilib_for_link( 'sequen', 'sequen.o', [], 'c' ); Der C-Compiler baut daraus libsequen.dll Er hängt lib davor. Diese dll wird anschließend mit
link("libsequen.dll", 'sequen', 'c'); gelinkt.

Zum Aufrufen wird in Scilab noch folgendes geschrieben:

function val = seq(n)
val = fort("sequen", n, 1, "i", "out", [1 n], 2, "i");
endfunction

Das ist dann der eigentliche Funktionsaufruf der "5" an die DLL übergibt.

seq(5)
ans =
0. 1. 2. 3. 4.

Aber da fällt mir gerade auf: Der Autor schreibt zum Abschluß: "A function for generating a sequence of integer numbers and returning a string"
Hat das was mit String-Verarbeitung in DLL's zu tun? Da sollte doch PChar Verwendung finden.

Ich habe auch schon das hier in FPC umgesetzt und es hat auf Anhieb funktioniert:

#include <math.h>
void myfunc(int *n, double *x, double *fval, int *iflag)
{
*fval = cos(*x)*(*x)*(*x) - 1;
}


FPC

library myfun;
uses math;
procedure myfunc(var n: integer; var x: double; var fval: double; var iflag: integer); cdecl;
begin
fval = cos(x)*(x)*(x) - 1;
end;
exports
myfunc;
begin
end.


Das ging einwandfrei.
link('myfun.dll', 'myfunc', 'c');

Aufruf in scilab allerdings:
y0=10;
y=fsolve(y0,'myfunc')
y =
11.003833

Hier stand allerdings die DLL direkt zur Verfügung und musste nicht erst noch in diesen FORTRAN/C-Aufruf "fort("sequen", n, 1, "i", "out", [1 n], 2, "i")"
eingebunden weden.

Gruß

Volker

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Ich habe den Doppelpunkt eben unterschlagen
fval = cos(x)*(x)*(x) - 1; soll sein: fval:= cos(x)*(x)*(x) - 1; sonst geht's nicht.

Meine FPC Version ist 2.2.4 Am 26.11.09 runtergeladen und installiert. Lazarus ist momentan gerade nicht vorhanden.

out ist dem compiler schon bekannt. Nur aus in verbindung mit "Variable" wollte er nicht.

Rechte Maustaste auf fp im Binary-Verzeichnis bringt leider keine genauere Versionsinfo.

Gruß

Volker

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Das ist Mein kompletter Quelltext in der FPC-IDE getippt und mit F9 erstellt:

library sequenz;

procedure sequen(ein: PInteger; aus: PInteger); cdecl;
var i: integer;
begin;
for i:=0 to ein^-1 do aus:=i;
end;

exports
sequen;

begin
end.


Volker

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Vergleich "FPC" mit "C"

Beitrag von RSE »

Hast du es mal mit ^Smallint probiert, wie ich es oben gepostet habe?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Hallo es funzt :D

@RSE: Wenn ich in die Prozedur ^Smallint, oder ^integer geschrieben habe, dann hat der Compiler gemeckert.
Ich musste vorher mit type Vint = ^Smallinteger erst den Zeiger generieren.

Aber ich hab' mal Lazarus heruntergeladen (0.9.28.2 mit fpc 2.2.4) wobei in der ide beta angezeigt wird
und das hier geschrieben.

library sequenz;

{$mode objfpc}{$H+} <<liegt es evtl. hier drann?

uses
Classes
{ you can add units after this };
procedure sequen(ein: PInteger; aus: PInteger); cdecl;
var i: integer;
begin
for i:=0 to ein^-1 do aus:=i;
end;
exports
sequen;
begin
end.

Das hat funktioniert.

Danke nochmal!!!!

und jetzt ab in die Koje, um 6 scheppert der Wecker..

ErnstVolker
Beiträge: 351
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Vergleich "FPC" mit "C"

Beitrag von ErnstVolker »

Nachdem ich den FPC Compiler unter Optionen auf Delphi compatibel umgestellt habe funktioniert auch der Quelltext:

Code: Alles auswählen

library sequenz;
 
procedure sequen(var ein: integer; var aus: array of integer); cdecl;
var i: integer;
begin;
   for i:=0 to ein-1 do aus[i]:=i;
end;
 
exports
   sequen;
 
begin
end.
Hier wollte er dann kein PInteger mehr bzw. hat in der Schleife bei aus:=i nach einem array verlangt.
Wenn ich es so mache:

library sequenz;

Code: Alles auswählen

procedure sequen(ein: PInteger; aus: array of Pinteger); cdecl;
var i: integer;
begin;
   for i:=0 to ein^-1 do aus[i]^:=i;
end;
 
exports
   sequen;
 
begin
end.
dann stürzt scilab ab.

Gruß

Volker

Antworten