Interfaces als Schnittstelle in Librarys verwendbar?
-
- 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:
Interfaces als Schnittstelle in Librarys verwendbar?
Zu meinem Projekt: Ich programmiere einen Mediaplayer, den ich gerade neu strukturiere. Die GUI stellt das Hauptprogramm dar (weil Forms in Bibliotheken noch nicht möglich ist). Der Kern des Players soll im ersten Plugin als Bibliothek realisiert sein (DLL unter Windows). Dieser Kern soll dann mit weiteren vom Kern geladenen Bibliotheken als Plugins erweitert werden können. Das Projekt soll Closed Source bleiben, die Schnittstellen zwischen den Komponenten möchte ich aber veröffentlichen. Nun dachte ich an Interfaces, die ich zur Schnittstellenbeschreibung in einer eigenen Unit benutzen möchte. Diese eine Unit soll dann mit der Komponente mitgeliefert werden, als Schnittstellenbeschreibung. Das Kernobjekt des Mediaplayers (MPlayer) im ersten Plugin (momentan noch direkt als Unit eingebunden), wird im initialization-Abschnitt erstellt und unter finalization wieder freigegeben.
[GUI (Hauptprogramm)] -------- [Mediaplayer] --------- [weitere Plugins]
1. Frage: Kann man Interfaces in einer Library überhaupt so exportieren, wie ich mir das denke? Meine Kernklasse in der Mediaplayer-Komponente soll ein Interface implementieren, welches dann im GUI benutzt werden können soll.
2. Frage: Es gibt ja 2 Arten von Interfaces in FPC: Die referenzgezählten COM-Interfaces und die nicht referenzgezählten CORBA-Interfaces. Um zwischen ihnen umzuschalten, gibt es den Compilerswitch {$INTERFACES CORBA}. Wo muss dieser Compilerswitch hin? Er ist im Programmers Guide 1x unter lokale Direktiven und 1x unter globale Direktiven aufgeführt, mit der gleichen Syntax. Wenn ich sie einmal in die Interfaces-Unit der Mediaplayer-Komponente reinschreibe (damit es allen Benutzern des Interfaces sichtbar ist), gilt sie dann in der gesamten Mediaplayer-Komponente? Ich kann die Unit ja zuallererst einbinden.
[GUI (Hauptprogramm)] -------- [Mediaplayer] --------- [weitere Plugins]
1. Frage: Kann man Interfaces in einer Library überhaupt so exportieren, wie ich mir das denke? Meine Kernklasse in der Mediaplayer-Komponente soll ein Interface implementieren, welches dann im GUI benutzt werden können soll.
2. Frage: Es gibt ja 2 Arten von Interfaces in FPC: Die referenzgezählten COM-Interfaces und die nicht referenzgezählten CORBA-Interfaces. Um zwischen ihnen umzuschalten, gibt es den Compilerswitch {$INTERFACES CORBA}. Wo muss dieser Compilerswitch hin? Er ist im Programmers Guide 1x unter lokale Direktiven und 1x unter globale Direktiven aufgeführt, mit der gleichen Syntax. Wenn ich sie einmal in die Interfaces-Unit der Mediaplayer-Komponente reinschreibe (damit es allen Benutzern des Interfaces sichtbar ist), gilt sie dann in der gesamten Mediaplayer-Komponente? Ich kann die Unit ja zuallererst einbinden.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
1. Dazu sind Interfaces da 
2. Der switch muss dort hin, wo du die interfaces definierst. Also quasi in die "shared unit" (immerhin müssen die Bibliothek und dein Hauptprogramm ja beide die gleiche Interface Deklaration nutzen, da bietet es sich an, die auch für beide als eine unit zu benutzen).

2. Der switch muss dort hin, wo du die interfaces definierst. Also quasi in die "shared unit" (immerhin müssen die Bibliothek und dein Hauptprogramm ja beide die gleiche Interface Deklaration nutzen, da bietet es sich an, die auch für beide als eine unit zu benutzen).
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Okay, dann kann ich jetzt meine weitergehenden Fragen stellen 
Wie man Interfaces definiert und Klassen definiert, die Interfaces implementieren, ist leicht zu finden und gut dokumentiert. Was ich allerdings vergeblich gesucht habe, ist, wie man sie verwendet. Vor ein paar Tagen hatte ich eine gute Seite dazu gefunden. Leider hab ich sie wieder geschlossen, weil ich zu dem Zeitpunkt keine Zeit hatte mich tiefgreifend damit zu befassen. Jetzt finde ich sie nicht mehr...
Wie exportiere ich ein Interface aus einer DLL? Wie das mit Prozeduren funktioniert weiß ich inzwischen, aber ich nehme an, man kann nicht einfach "exports IMyInterface" schreiben. Und wie läuft dann die Benutzung des Interfaces "auf der anderen Seite" ab? Die leere Hülle des Interfaces ist ja dann bekannt (durch die unit), diese muss nun irgendwie mit der Implementation geimpft werden. Dazu muss ich mir sicherlich irgendwelche Zeiger aus der Library holen (mittels einer exportierten Prozedur). Kann mir da bitte jemand ein Beispiel geben (gern auch einen Link)?

Wie man Interfaces definiert und Klassen definiert, die Interfaces implementieren, ist leicht zu finden und gut dokumentiert. Was ich allerdings vergeblich gesucht habe, ist, wie man sie verwendet. Vor ein paar Tagen hatte ich eine gute Seite dazu gefunden. Leider hab ich sie wieder geschlossen, weil ich zu dem Zeitpunkt keine Zeit hatte mich tiefgreifend damit zu befassen. Jetzt finde ich sie nicht mehr...
Wie exportiere ich ein Interface aus einer DLL? Wie das mit Prozeduren funktioniert weiß ich inzwischen, aber ich nehme an, man kann nicht einfach "exports IMyInterface" schreiben. Und wie läuft dann die Benutzung des Interfaces "auf der anderen Seite" ab? Die leere Hülle des Interfaces ist ja dann bekannt (durch die unit), diese muss nun irgendwie mit der Implementation geimpft werden. Dazu muss ich mir sicherlich irgendwelche Zeiger aus der Library holen (mittels einer exportierten Prozedur). Kann mir da bitte jemand ein Beispiel geben (gern auch einen Link)?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Die interfaces verwendest du ähnliche wie Klassen auch ...
var
bla: IMyInterface;
begin
bla := MyObject; //MyObject implements IMyInterface
...
end;
Bei einer DLL würde man das dann in etwa so nutzen:
function CreateMyObject: IMyInterface;
begin
Result := TMyObject.Create;
end;
exports
CreateMyObject;
Dann sollte man allerdings entweder die refcounted com interfaces nehmen, oder eine methode in das interface aufnehmen, um das Objekt wieder freizugeben (am einfachsten natürlich einfach .Free
).
var
bla: IMyInterface;
begin
bla := MyObject; //MyObject implements IMyInterface
...
end;
Bei einer DLL würde man das dann in etwa so nutzen:
function CreateMyObject: IMyInterface;
begin
Result := TMyObject.Create;
end;
exports
CreateMyObject;
Dann sollte man allerdings entweder die refcounted com interfaces nehmen, oder eine methode in das interface aufnehmen, um das Objekt wieder freizugeben (am einfachsten natürlich einfach .Free

-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Hm, dann brauch ich das Interface also gar nicht exportieren... Ich habe vor, die Klasse zu instanzieren, wenn die Bibliothek geladen wird und wieder freizugeben, wenn sie entladen wird. Dass dieses Interface nicht mehr benutzbar ist, wenn die Library entladen ist, sollte ja sowieso klar sein, also brauch ich auch keine Referenzzählung. Dann brauch ich also lediglich noch eine Funktion zu exportieren, die einen Pointer auf diese Instanz zurückgibt, und zwar als Typ des Interfaces. Krass, wie einfach das ist, daher ist auch keine große Doku darüber vorhanden :-p
Vielen Dank!
Edit:
Das heißt sicherlich auch, dass ich jede Methode des Interfaces mit "{$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}" definieren sollte und im Interface nur mit PChar statt String arbeiten muss usw., alles das, was von Librarys bekannt ist, um mit anderen Programmiersprachen kompatibel zu bleiben.
Um das ReferenceCounting abzustellen, muss ich 1x {INTERFACES CORBA} einbauen und dann kann ich sicherlich auch direkt von TObject ableiten, also TMPlayer = class(TObject,IMPlayer), richtig? Oder brauch ich da noch TAggregatedObject oder TContainedObject?
Vielen Dank!
Edit:
Das heißt sicherlich auch, dass ich jede Methode des Interfaces mit "{$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}" definieren sollte und im Interface nur mit PChar statt String arbeiten muss usw., alles das, was von Librarys bekannt ist, um mit anderen Programmiersprachen kompatibel zu bleiben.
Um das ReferenceCounting abzustellen, muss ich 1x {INTERFACES CORBA} einbauen und dann kann ich sicherlich auch direkt von TObject ableiten, also TMPlayer = class(TObject,IMPlayer), richtig? Oder brauch ich da noch TAggregatedObject oder TContainedObject?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
Re: Interfaces als Schnittstelle in Librarys verwendbar?
Dass muss man nicht bei jeder Prozedur machen. $calling reicht:RSE hat geschrieben: Das heißt sicherlich auch, dass ich jede Methode des Interfaces mit "{$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}" definieren sollte
http://lazarus-ccr.sourceforge.net/fpcd ... 120001.1.7" onclick="window.open(this.href);return false;
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Auch nicht uninteressant! Wenn ich davon ausgehe, dass die calling conventions von der Interfacedefinition auf die implementierende Klasse vererbt werden, dann könnte ich also in die Interface-Unit oben {$IFDEF WINDOWS} {$CALLING stdcall} {$ELSE} {$CALLING cdecl} {$ENDIF} und unten dann {$CALLING default} einbauen und alles ist in Butter. 

Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
So einfach wird das nicht. Irgendwo willst du das Interface ja auch implementieren, und dann müssen die Calling Conventions mit der Definition des Interfaces übereinstimmen. Also müsstest du dann entweder diese ganze Unit auch auf eine andere Calling Convention setzen, oder eben doch wieder jede einzelne Funktion einzeln abändern.
Was spricht denn dagegen, durchweg stdcall zu nehmen? Soweit ich weiss, hat auch gcc damit keine Probleme (auch, wenn es vlt. eher unüblich ist).
Was spricht denn dagegen, durchweg stdcall zu nehmen? Soweit ich weiss, hat auch gcc damit keine Probleme (auch, wenn es vlt. eher unüblich ist).
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Ganz einfach: Ich habe keine Ahnung von den Auswirkungen. Delphi (und FPC) wird nicht ohne Grund eine andere calling convention haben als der Rest der Windows-Welt und wahrscheinlich werden bestimmte Sachen darauf optimiert sein. Wenn du definitiv weißt, dass es keine Auswirkungen hat, dann wundere ich mich, warum nicht stdcall bzw. cdecl die default calling convention in {$mode objfpc} ist. Irgendwo muss es Unterschiede geben.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- Beiträge: 1104
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Aber dann werden macros die nach prozeduren gewandelt werden davon auch betroffen.theo hat geschrieben:Dass muss man nicht bei jeder Prozedur machen. $calling reicht:RSE hat geschrieben: Das heißt sicherlich auch, dass ich jede Methode des Interfaces mit "{$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}" definieren sollte
http://lazarus-ccr.sourceforge.net/fpcd ... 120001.1.7" onclick="window.open(this.href);return false;
Ich habe darueber gedacht, und versuche mal:
#ifdef windows
-dmycall:=stdcall
#else
-dmycall:=cdecl
#endif
zum fpc.cfg zu addieren (ungetested)
und nutze dan im Source einfach
procedure xx; mycall;
Wenn man das nicht im fpc.cfg mag, oder es nicht funktioniert, kann man auch
{$macro on}
{$ifdef windows} // win32,win64 und wince
{$define mycalling:=stdcall}
{$else}
{$define mycalling:=cdecl}
{$endif}
die FPC Sourcen nutzen dass schon.
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Ich denke das gefällt mir am besten, auch wenn ich das bei jeder Methode einzeln angeben muss.marcov hat geschrieben:{$macro on}
{$ifdef windows} // win32,win64 und wince
{$define mycalling:=stdcall}
{$else}
{$define mycalling:=cdecl}
{$endif}
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Um unter Windows zu testen, ob Du den Export des Interfaces aus der DLL richtig gemacht hast, nimm eine entsprechende IDE (wie Delphi oder Visual Studio), die eine Funktion, die z.B. "Type Library importieren" heißt, hat. Delphi baut einem dann aus den Infos einer entsprechend ausgestatteten DLL (die exportiert dann mehr als eine Standard DLL, die nur eine Einsprungtabelle ohne Funktionsnamen etc. zeigt) eine Unit, die alle Funktionen und auch Interfaces der DLL zugreifbar macht. Neben DLLs haben auch diverse andere Dateiformate "Type Library"-Informationen (exe und einige weitere)
So kann Delphi z.B. die API für einen installierten Adobe Flash Player importieren.
Soweit ich weiß hat Lazarus leider kein "Type Library importieren". Ich weiß auch nicht wie man mit Lazarus (oder Delphi) eine DLL erzeugt, die iese Informationen exportiert. Ich habe aber schon ein mit Delphi erzeugtes exe gesehen, das eine Type Library exportiert.
-Michael
So kann Delphi z.B. die API für einen installierten Adobe Flash Player importieren.
Soweit ich weiß hat Lazarus leider kein "Type Library importieren". Ich weiß auch nicht wie man mit Lazarus (oder Delphi) eine DLL erzeugt, die iese Informationen exportiert. Ich habe aber schon ein mit Delphi erzeugtes exe gesehen, das eine Type Library exportiert.
-Michael
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Ich habe weder Delphi noch Visual Studio zur Verfügung. Außerdem würde ich damit vielmehr testen, ob ich die Type Library korrekt exportiert habe, nicht (nur) meine Funktionen.
Ich denke, wenn ich die selbst erstellte Library verwenden kann, reicht mir das, wenn später Fehler auftreten, die mir zugetragen werden, dann kann ich mich immernoch drum kümmern. Das wäre zwar unschön, aber eben keine Katastrophe. Trotzdem danke für diesen Tipp.

Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- Beiträge: 203
- Registriert: Di 22. Sep 2009, 13:08
- OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
- CPU-Target: xxBit
Re: Interfaces als Schnittstelle in Librarys verwendbar?
Der Type-Library-Import ist aber wohl nur für COM-DLLs (ActiveX). Die müssen in Windows immer recht umständlich installiert werden - kann man sowas auf Linux überhaupt zum Laufen bringen?mschnell hat geschrieben:Um unter Windows zu testen, ob Du den Export des Interfaces aus der DLL richtig gemacht hast, nimm eine entsprechende IDE (wie Delphi oder Visual Studio), die eine Funktion, die z.B. "Type Library importieren" heißt, hat. Delphi baut einem dann aus den Infos einer entsprechend ausgestatteten DLL (die exportiert dann mehr als eine Standard DLL, die nur eine Einsprungtabelle ohne Funktionsnamen etc. zeigt) eine Unit, die alle Funktionen und auch Interfaces der DLL zugreifbar macht. Neben DLLs haben auch diverse andere Dateiformate "Type Library"-Informationen (exe und einige weitere)
Mit Delphi kann man noch RuntimePackages verwenden, was noch ein wenig komfortabler ist als DLLs. Allerdings hat man es dann wohl schwerer die von anderen Programmiersprachen aus anzusprechen.
Ich habe zwar früher ein paar COM-Dlls gemacht, bin aber doch lieber auf normale Dlls und Delphi Packages umgestiegen.
Was ich ideal fände, wäre eine normale .DLL oder .SO, über die man an eine ganz normale Interface-Referenz herankommt - allerdings muß man noch ziemlich aufpassen, dass Dll und Anwendung vom Speichermanager her miteinander klarkommen...
Weiss jemand, ob das unter Linux so einfach funktioniert, oder gibt es da noch irgendwelche prinzipiellen Probleme?
Interessant wäre natürlich auch sich in .NET-Assemblies einzuklinken...
-
- 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: Interfaces als Schnittstelle in Librarys verwendbar?
Ich glaube das ist genau das, was ich vorhabe. Eine .DLL oder .SO, die ich per Dateiname als Plugin identifiziere und ggf. lade. Die Library stellt ein Interface ohne Referenzzählung ({$INTERFACES CORBA}) und eine Prozedur, die einen Zeiger auf die Implementation dieses Interfaces zurückliefert (Typ des Zeigers ist das Interface) zur Verfügung und das wars. Instanziert wird in dieser Prozedur, freigegeben beim Entladen der Library.Patito hat geschrieben:Was ich ideal fände, wäre eine normale .DLL oder .SO, über die man an eine ganz normale Interface-Referenz herankommt
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!