AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Zitat:
|
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Vielleicht hilft Dir das ja weiter:
http://www.delphipraxis.net/183846-f...nshutdown.html und natürlich Quelltext FastMM |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Zitat:
Trotzdem bleibt für mich immer noch das Problem, dass ich noch nicht den 100%igen Durchblick habe, wie ich denn die DLL jetzt aufbauen muss. Kann da vielleicht mal jemand ein kleines Beispiel machen. Pseudoabfrage von einem SQL-Server und Übergabe der Daten an mein Programm. Die Funktion wird dann logischerweise aus dem Programm heraus aufgerufen. Wäre sowas machbar? |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Also wir benutzen Interfaces. Das hat den enormen Vorteil, dass die reine DLL Schnittstelle sehr schlank sein kann. Wir haben eine Funktion in der DLL, die von der Anwendung aufgerufen wird nachdem die DLL geladen ist. Diese bekommt das Anwendungsinterface. Darüber meldet sich umgekehrt die DLL an der Anwendung an und übergibt ebenfalls ein Interface.
Darüber können nun Interfaces bei der Anwendung registriert oder angefordert werden. Es gibt eine Klasse TApplicationInterface, die das ganze kapselt. Und dann geht das ganze direkt generisch. Zum Beispiel funktioniert dann das sowohl in DLL als auch in der Anwendung:
Delphi-Quellcode:
Interfaces kennen ja nun keine generischen Methodenparameter. Das funktioniert daher, indem die Klassenmethode Get die GUID des generischen Parameters ermittelt und über das Interface an der Hauptanwendung diese GUID und das Parameterinterface übergibt. Dort wird dann über die GUID die registrierte Factorymethode ermittelt, mit der das Interface geholt werden kann, und mit dem Parameterinterface aufgerufen.
var
Params: IInterfaceGetterParams; Data: IDataset; begin Params := TDatabaseGetterParams.Create(TDatasetKind.Query, 'select * from foo'); Data := TApplicationInterface.Get<IDataset>(Params); while not Data.Eof do ... Natürlich kann man bei wenigen Interfaces (bei uns sind es eben sehr viele) auch im Interface der Hauptanwendung direkt z.B. eine Methode GetDataset: IDataset usw. anlegen und braucht keine Generics dafür. |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Also Interfaces würde ich ja auch benutzen. Das steht außer Frage. Nur stehe ich auf dem Schlauch, was das Abrufen von Ergebnissen vom SQL-Server und das Übergeben der Ergebnisse an die Anwendung angeht. Innerhalb meiner Anwendung würde ich die Ergebnisse gerne in Form eines Objektes zwischenspeichern. Um mal bei den Benutzern zu bleiben als Instanz bzw. mehrere Instanzen eines TUser Objektes.
Wäre es sinnvoll so etwas zu tun? Nur mal als Beispiel und hier im Editor runtergetippt.
Delphi-Quellcode:
Die DLL Exportiert dann eine Funktion GetUsers oder wahlweise auch GetInstance die als Parameter eine Instanz eines IUserExchanger Objektes erwartet.
IUserExchanger = interface(IInterface)
procedure AddNewUser(const Username: string; FirstName: string; LastName: string); procedure AddUserGroup(const ID: Integer; const Name: string); [...] end;
Delphi-Quellcode:
IUserInterface = interface(IInterface)
procedure GetUsers(UserExchanger: IUserExchanger); end;
Delphi-Quellcode:
Nur mal so ein Gedanke. Falls da etwas unklar sein sollte, dann versuche ich gerne es etwas besser zu beschreiben.
TUserExchanger = class(TInterfacedObject, IUserExchanger)
private FUsers: TObjectList<TUser>; User: TUser; public procedure AddNewUser(const Username: string; FirstName: string; LastName: string); procedure AddUserGroup(const ID: Integer; const Name: string); end; implementation procedure TUserExchanger.AddNewUser(const Username: string; FirstName: string; LastName: string); begin User := TUser.Create; User.UserName := UserName; User.FirstName := FirstName; User.LastName := LastName; FUsers.Add(User); end; procedure TUserExchanger.AddUserGroup(const ID: Integer; const Name: string); begin User.Groups.Add(ID, Name); end; Macht man so etwas oder gibt es da Nachteile? Laut Zacherl wäre es ja auch mittlerweile kein Problem mehr, Strings direkt auszutauschen. Beide Anwendungen die darauf zugreifen sind in Delphi geschrieben. Wenn das doch nicht gehen sollte, würde dann so etwas funktionieren? Bitte auf das PChar achten. Das Interface habe ich hierfür nicht extra noch einmal geschrieben.
Delphi-Quellcode:
procedure TUserExchanger.AddUserGroup(const ID: Integer; const Name: PChar);
var LName: string; begin LName := Name; User.Groups.Add(ID, LName); end; |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Hat hierzu noch jemand eine Idee? Kann man das so machen bzw. macht man das überhaupt so wie in meinem Beispiel gezeigt?
Wenn nicht, dann wäre es super wenn mir vielleicht jemand ein Beispiel machen könnte wie man so etwas am Elegantesten löst. Ich finde hierzu irgendwie keine passenden Informationen oder kann sie zumindest nicht auf meinen Fall anwenden. |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Irgendwie kann ich mir nicht vorstellen, dass noch niemand eine DLL in Delphi geschrieben haben soll. :(
Da muss es doch einfache Möglichkeiten geben sowas zu machen. Ich zähle nochmal kurz auf, was ich benötige:
Alternativ, wie kann man es besser bzw. anders machen. Ich habe gefühlt jedes Tutorial welches etwas mit DLLs zu tun hat durch. Trotzdem bin ich in dem Punkt nicht wirklich schlauer. Wäre super wenn vielleicht doch noch jemand einen Tipp für mich hat. Wenn etwas unklar sein sollte bei dem was ich benötige, dann fragt mich bitte. Ich bin über jede Antwort die mich weiterbringt dankbar. :| |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Wenn eine Schnittstelle zu anderen Programmen zur Verfügung gestellt werden muss ist man mit (Delphi-) DLL's beschränkt. Deshalb arbeiten wir seit mehr als 10 Jahren mit RemObjects. Damit kannst Du Multitier Anwendungen erstellen und eine sehr komfortable IPC realisieren. Durch die Auswahl unzähliger Channels ist es möglich jedem eine Schnittstelle zu bieten und intern mit dem Objekten zu arbeiten (eher komfortable Records/Arrays). Du musst Dich nicht um Verbindungen, Reconnectes usw. kümmern. Ausserdem kann auch mit Events gearbeitet werden. Ist jetzt nicht direkt eine Antwort auf Deine DLL Frage. Einfach ein anderer Ansatz (der natürlich etwas kostet).
|
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Hallo taveuni,
sieht ja auch interessant aus. Nur wollte ich das alles für den Anfang ein wenig kleiner halten. Bin leider auch nicht so ein Freund davon, direkt Komponenten für ein Vorhaben zu kaufen. So etwas sollte sich ja eigentlich problemlos mit DLLs lösen lassen. Wenn man es denn kann. Interessant sieht das aus, keine Frage. Nur weiß ich eben auch nicht, ob dass das Richtige für mich/uns ist. Und der Preis ist ja auch nicht gerade gering (um es mal vorsichtig auszudrücken). :o Eine Testversion halte ich da nicht für angebracht. Ich denke, dass ich da bestimmt länger bräuchte um mich da einzuarbeiten als es der Testzeitraum zulässt. Und bevor ich nachher merke, dass es doch nicht das Richtige ist ... aber danke für den Vorschlag. Was gäbe es denn für Alternativen? Ich habe schon sehr viel von REST gehört, weiß aber nicht ob das für meinen Fall das Richtige wäre. Könnte man das dafür verwenden? Vorteil wäre ja auch, dass ich theoretisch die Grundlage für eine Mobile Anwendung geschaffen hätte. Ist das korrekt? |
AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Um auf Deine DLL Frage zurückzukommen:
In eine DLL Schnitstelle gehören nur einfache Typen, also z.B Integer, Word, Double, Single, PWideChar, PAnsiChar etc.. Auf keinen Fall normale Strings. Records auch nur aus diesen Typen Das hat den Vorteil das man Compilerunabhängig ist. Wir benutzen das heftig in mixed Projekten (Delphi, VCC, und sogar noch Fortran) Für Records (Structs) gilt dasselbe also z.B Delphi :
Delphi-Quellcode:
//C++
const
cwmaxnamesize = 30; type tApi_Materialrec = packed record Name: array [0 .. cwmaxnamesize - 1] of Ansichar; Group: array [0 .. cwmaxnamesize - 1] of Ansichar; MatCode: array [0 .. cwmaxnamesize - 1] of Ansichar; Mate1, mate2, mate3, matg1, matg2, matgew: single; // Materialgewicht Mattyp: integer; list_matbez, mat_photoflag, mat_photo1, mat_photo2: integer; end;
Code:
Wenn Wir Interfaces benutzen gilt dasselbe.
// Ausrichtung an Byte-Grenzen wegen Delphi
#pragma pack(push,1) struct CHA_API_API Api_mat { char name[30], Group[30], MatCode[30]; float mate1,mate2,mate3, matg1,matg2,matgew; int mattyp; int list_matbez; int photoflag, Photo1, Photo2; }; einziger Unterschied ist das wir in Interface auch schon mal WideString benutzen, da dort das Speichermanagement von Windows grift. Funktionen geben niemals Records zurück sondern sind bei uns immer aufgebaut nach dem Schema:
Delphi-Quellcode:
Das funktioniert bei uns soweit problemlos.
function getMatDataforId(aid : Integer; var matrec : tApi_Materialrec) : Bool;
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz