Bibliothek für C und Pascal schreiben

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Hallo!
Ich habe folgendes problem: Ich habe eine Bibliothek in Pascal geschrieben, welche relativ komplexe Objekte (d.H. es werden String-Listen, Records und Arrays zwischen anwendung und Library hin- und hergeschoben) enthält und diese den Anwendungen zugängig macht.
Nun soll diese Bibliothek aber auch von in C und in C++ geschriebenen Anwendungen genutzt werden können. Wie mache ich eine Library C-Kompatibel? Aus meiner Delphi-Zeit weiß ich noch, dass man anstelle von Strings PAnsiChars verwenden soll, das war's aber auch schon. Damals war das Thema auch noch nicht wichtig.
Hat jemand eine Anleitung, wie soetwas am besten zu bewerkstelligen ist? Das ganze findet ausschließlich unter Linux statt.

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: Bibliothek für C und Pascal schreiben

Beitrag von Hitman »

Ich denke da gibt es zwei prominente Möglichkeiten:

1. Du exportierst "flache" Funktionen. Die WinAPI ist ein gutes Beispiel für objektorientierte Konzepte, die in flacher Form nach außen zur Verfügung stehen.
Das sieht dann in etwa so aus:

Code: Alles auswählen

function MyObjectDoSomething(AHandle: Pointer; AParam1: Integer; AParam2: PChar): Integer;
begin
  Result := TMyObject(AHandle).DoSomething(AParam1, PChar(AParam2));
end;
 
exports
  MyObjectDoSomething;
2. Du arbeitest mit (COM) Interfaces. Dazu findest du genügend (über Delphi) im Netz. Und unter C sollte es möglich sein, diese dann zu nutzen.

Es mag vielleicht noch andere Möglichkeiten geben, aber die zwei scheinen mir die sinnvollsten ;)

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

Re: Bibliothek für C und Pascal schreiben

Beitrag von theo »

Nur einfache, nicht referenzgezählte Typen hin- und herschieben (Pchar, Integer, Boolean evtl. einfache Arrays...)

z.B. StringListe: Entweder nur Text austauschen, oder wie Hitman sagte, die nötigen Funktionen der Klasse abflachen und exportieren.

à la:

Code: Alles auswählen

Handle=TStringList_Create;
TStringList_Add(Handle, APchar);
APchar=TStringList_GetText(Handle);
TStringList_Free(Handle);

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Abflachen würde schon funktionieren, mit einigen Funktionen. Allerdings muss sich das Objekt selbst eine Menge an Daten merken, welche dann über einzelnen propertys abgerufen werden... So würde immer ein leeres Objekt genutzt und das funktioniert so nicht.
Wie kann ich z.B. auch Arrays eines Records wie z.B.:

Code: Alles auswählen

TXY = record
 a,b,c: String;
 d: Integer;
end;
für C nutzbar machen? Gibt es da nicht vielleicht irgendeine Objekt-Kompatibilitätsschicht?
COM wird unter Linux kaum verwendet, ich werde mich darüber aber mal informieren. Am elegantesten wäre es, DBus zu nutzen, aber die Pascal-Implementierung dafür ist schlicht unbrauchbar.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Bibliothek für C und Pascal schreiben

Beitrag von mschnell »

Wenn Du mit "C" normales C meinst, musst Du sowieso "abflachen", weil C gar keine Objekte, Strings etc kennt.

Wenn Du aber "C++" meinst, gehen Objekte und Strings auch nicht, weil, soweit ich weiß, die Objekt ABI in (GNU) C++ anders ist und nicht kompatibel zu FPC.

-Michael

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

Re: Bibliothek für C und Pascal schreiben

Beitrag von theo »

Targion hat geschrieben: So würde immer ein leeres Objekt genutzt und das funktioniert so nicht.
Wie meinst du das? Das Objekt existiert, bis du in C im Beispiel wieder TStringList_Free(Handle); aufrufst.
Den Array of Record könnte man auch als Pchar austauschen, z.B. XML, JSON.... es könnte aber auch so gehen, da bin ich mir nicht 100% sicher.
Dann darfst du aber keinen String sondern musst Pchar verwenden.
S.a. http://de.wikipedia.org/wiki/JavaScript_Object_Notation" onclick="window.open(this.href);return false;
http://www.hu.freepascal.org/lists/fpc- ... 15126.html" onclick="window.open(this.href);return false;
http://sourceforge.net/projects/jsontoolkit/" onclick="window.open(this.href);return false;

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Super, JSON ist glaube ich schon eine smarte Lösung für die Sache. Ich probiere das einfach aus, mal sehen ob es funktioniert!

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Ich bin noch nicht dazu gekommen, JSON auszuprobieren, da ich im Moment noch ein anderes Problem habe: Wie kann ein C++ Programm, oder überhaupt auch ein Pascal-Programm, ein Event an einer Bibliothek registrieren?
Wenn z.B. eine Funktion ein Event als Parameter erwartet.

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

Re: Bibliothek für C und Pascal schreiben

Beitrag von theo »

Das nennt sich callback und ist ein Prozedurzeiger.

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: Bibliothek für C und Pascal schreiben

Beitrag von Hitman »

Also im Prinzip genauso wie innerhalb von Pascal auch. Die ganze LCL funktioniert über Callbacks. (Form1.OnShow := @Form1Show; )

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Wenn ich also sowas habe:

Code: Alles auswählen

TMessageEvent = procedure(Sender: TObject;msg: String) of object;
function remove_app(aid: String; msg: TMessageEvent; fast: Boolean=false;
Kann ich das 1:1 in der Lib nutzen, und in C wie in Pascal einfach die Adresse der Prozedur übergeben?

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

Re: Bibliothek für C und Pascal schreiben

Beitrag von theo »

Targion hat geschrieben:Wenn ich also sowas habe:

Code: Alles auswählen

TMessageEvent = procedure(Sender: TObject;msg: String) of object;
function remove_app(aid: String; msg: TMessageEvent; fast: Boolean=false;
Kann ich das 1:1 in der Lib nutzen, und in C wie in Pascal einfach die Adresse der Prozedur übergeben?
"of object" schon mal nicht.
Das muss eine normale Prozedur sein:

procedure Test(inp:Pchar); cdecl;
begin
//blah
end;

MeinRegisterCallbackInC(@Test);

Glaub ich auf die Schnelle ;-)

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Ah, also doch ein wenig anders. Danke für die Hilfe! (Bis jetzt habe ich nur Low-Level-DLLS geschrieben, z.B. für ein PlugIn-System. Diese waren dann aber auch nur mit Delphi erstellbar)

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Bibliothek für C und Pascal schreiben

Beitrag von Targion »

Eine Frage zum Event-Problem habe ich noch:
Wie veröffentliche ich das procedure Test(inp:Pchar); cdecl;? Und wie deklariere ich das in einer Funktion?

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

Re: Bibliothek für C und Pascal schreiben

Beitrag von theo »

Weiss nicht genau was du meinst.
Google mal ein bisschen zum Thema "Delphi Callback".
Z.b. hier http://www.delphipraxis.net/topic79374,0,asc,0.html" onclick="window.open(this.href);return false;

Antworten