AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?
Thema durchsuchen
Ansicht
Themen-Optionen

DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

Offene Frage von "MyRealName"
Ein Thema von Aviator · begonnen am 30. Sep 2016 · letzter Beitrag vom 13. Okt 2016
Antwort Antwort
Seite 4 von 5   « Erste     234 5      
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#31

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 10. Okt 2016, 17:09
Nun ja die Frage ist halt immer, muss es dynamisch sein?

Ansonsten Die Records fest deklarieren:
in etwa

Delphi-Quellcode:
teventrec = record
 Size : integer; // Muss gesetzt werden und entspricht sizeof(teventrec)
 matname : Array[0..99] of wchar; // 100 Zeichen
 x, y : Double;
 nochn_int : integer;
 matText : Array[0..199] of wchar; // 200 Zeichen
end;
So sparst Du Dir das freigeben und durch das Sizefeld kann auf beiden Seiten geprüft werden ob das alles noch zusammenpasst
Fritz Westermann
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#32

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 10. Okt 2016, 17:14
Nun ja die Frage ist halt immer, muss es dynamisch sein?
Hmm da hast du Recht. FirstName, LastName, E-Mail und Password haben in der Datenbank eine feste Länge von jeweils 50 oder 60 Zeichen. Die könnte ich mit einer festen Länge deklarieren.

Aber was mache ich mit dynamischen Längen? Die werden früher oder später auf jeden Fall kommen. Vielleicht nicht bei einem User aber bei bei einem Dokument. Oder geht es nur mit StrDispose() ?
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#33

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 10. Okt 2016, 17:47
Code:
Aber was mache ich mit dynamischen Längen? Die werden früher oder später auf jeden Fall kommen. Vielleicht nicht bei einem User aber bei bei einem Dokument.
Was Du machen kannst solange das alles bei Windows bleibt:

Verwende WideString in der Schnittstelle, der wird von Windows verwaltet.

Also anstatt Array[xx] of widechar ein
Name : Widestring;

Ist auf Delphi Seite sehr schön zu verwenden bei C++ etwas aufwendiger AKA BSTR* etc..

oder ein ganz anderer Ansatz übergebe Functions Pointer also so etwas wie

Delphi-Quellcode:
Type
  tAddDocument = function(ID : int64; const Value : PWidechar) : boolean;
in der Dll dann :

Delphi-Quellcode:
procedure FillDocument(ID : int64; afunc : TaddDocument);
  begin
    // Sehr vereinfacht
   if db.findid(id)
   afunc(id, db.getDocumantData(id));
  end;


in der exe:

Delphi-Quellcode:
 // Call to Dll
   FillDocument(ID, @myAddFunc);
Fritz Westermann
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#34

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 10. Okt 2016, 18:44
Statt PWideChar einfach WideString verwenden.

WideString ist eine "Umleitung" (Kapselung) auf einen OLE-String (der OleAut32.dll), den eigentlich jede Programmiersprache versteht und der auch von Windows bei vielen Schnittstellen Verwendung findet.
MSDN-Library durchsuchenSysAllocStringLen MSDN-Library durchsuchenSysFreeString MSDN-Library durchsuchenSysStringLen
Die Speicherverwalung wird dann von der OLE32 vorgenommen, womit also Einer den String erstellen und der Andere ihn wieder freigeben kann, da beide Seiten den selben Speichermanager verwenden.

Wenn diese DLL in der Delphi-Welt bleibt, also nur bei Delphi-Anwendungen eingebunden wird, dann kann man auch Delphi-Strings (AnsiString/UnicodeString) verwenden, wenn man SimpleShareMem (früher ShareMem) verwendet.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (10. Okt 2016 um 18:47 Uhr)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#35

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 11. Okt 2016, 11:13
Ich würde an dieser Stelle auch nicht mehr mit Records arbeiten.
Wenn schon Interface, dann auch für die Datenobjekte.
Delphi-Quellcode:
IEventObject = interface(IInterface)
  [GUID]
  function GetMatName: WideString;
  function GetX: Double;
  function GetY: Double;
  function GetNochn_Int: Integer;
  function GetMatText: WideString;
  property MatName: WideString read GetMatName;
  property X: Double read GetX;
  property Y: Double read GetY
  property Nochn_Int: Integer read GetNochn_Int;
  property MatText: WideString read GetMatText;
end;

TEventObject = class(TInterfacedObject, IEventObject)
private
  FMatName: WideString;
  FX: Double;
  FY: Double;
  FNochn_Int: Integer;
  FMatText: WideString;
protected
  function GetMatName: WideString;
  function GetX: Double;
  function GetY: Double;
  function GetNochn_Int: Integer;
  function GetMatText: WideString;
public
  {...}
end;


function GetEventObject(ID: Int64): IEventObject;
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#36

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 11. Okt 2016, 16:44
Ich würde an dieser Stelle auch nicht mehr mit Records arbeiten.
Wenn schon Interface, dann auch für die Datenobjekte.
Das muss ich mir mal anschauen. Records sind in dem Fall zwar einfacher zu handlen wenn ich ein Array of Record benutze, aber Interfaces sind auch ganz schön. Dann müsste ich natürlich für jeden User eine eigene Interface Instanz erzeugen.

Wie gesagt, schaue ich mir mal an ob ich das so umsetzen kann. Wenn ich Rückfragen dazu habe, dann melde ich mich.

  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#37

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 11. Okt 2016, 19:01
Hallo Blup (und alle anderen Helfer),

da bin ich schon wieder. Funktioniert doch nicht so ganz wie ich das will.

Ich habe beim Erstellen des Interfaces Probleme mit den Datentypen. Ich wollte jetzt bei PWideChar bleiben und nicht wieder alles auf WideString o.ä. umstellen. Ich habe mir jetzt ein Interface erstellt, das wie folgt aussieht:

Delphi-Quellcode:
  IDMSUserExchange = interface(IInterface)
  [GUID]
    procedure SetChangePassAtNextLogon(const Value: Boolean);
    procedure SetDeactivated(const Value: Boolean);
    procedure SetEMail(const Value: PWideChar);
    procedure SetFirstName(const Value: PWideChar);
    procedure SetID(const Value: Int64);
    procedure SetLastName(const Value: PWideChar);
    procedure SetPassword(const Value: PWideChar);
    procedure SetPermissions(const Value: Int64);
    procedure SetUserName(const Value: PWideChar);

    function GetChangePassAtNextLogon: Boolean;
    function GetDeactivated: Boolean;
    function GetEMail: PWideChar;
    function GetFirstName: PWideChar;
    function GetID: Int64;
    function GetLastName: PWideChar;
    function GetPassword: PWideChar;
    function GetPermissions: Int64;
    function GetUserName: PWideChar;

    property ID: Int64 read GetID write SetID;
    property UserName: PWideChar read GetUserName write SetUserName;
    property FirstName: PWideChar read GetFirstName write SetFirstName;
    property LastName: PWideChar read GetLastName write SetLastName;
    property EMail: PWideChar read GetEMail write SetEMail;
    property Password: PWideChar read GetPassword write SetPassword;
    property Permissions: Int64 read GetPermissions write SetPermissions;
    property Deactivated: Boolean read GetDeactivated write SetDeactivated;
    property ChangePassAtNextLogon: Boolean read GetChangePassAtNextLogon write SetChangePassAtNextLogon;
  end;
Sobald ich jetzt aber eine Klasse erstelle welches das Interface implementiert, muss ich ja auch entsprechend mit PWideChar arbeiten. Innerhalb meines Programmes, also wenn die Daten von der DLL zurückgegeben wurden, würde ich aber ganz gerne mit string weiterarbeiten. Jetzt müsste ich mir ja theoretisch 2 Klassen erzeugen die das gleiche Interface implementieren und sich nur durch die internen Datentypen der privaten Felder unterscheiden würden.

Klasse, welche zum Austausch der Daten mit der DLL benutzt wird (da kein string nutzbar).
Delphi-Quellcode:
TDMSUserExchange = class(TInterfacedObject, IDMSUserExchange)
private
  FUserName: PWideChar;
  FEMail: PWideChar;
  [...]
  FDeactivated: Boolean;
public
  [Alle Interface Proceduren]
end;
Interne Klasse die zur Weiterverarbeitung benutzt werden soll:
Delphi-Quellcode:
TDMSInternalUserData = class(TInterfacedObject, IDMSUserExchange)
private
  FUserName: string; // <-- Hier string
  FEMail: string; // <-- Hier string
  [...]
  FDeactivated: Boolean;
public
  [Alle Interface Proceduren]
end;
Ist das jetzt übers Ziel hinaus geschossen oder muss das genau so gemacht werden? Wenn nicht, wie macht man das richtig? Dann müsste ja theoretisch wie es aktuell mit den Records auch der Fall ist die Objekte von TDMSUserExchange nach TDMSInternalUserData übertragen werden.

Wenn ich Speicher mit StrNew() anfordern muss, dann kann ich den ja nicht einfach wieder freigeben wenn ich intern Strings verwende. Oder verstehe ich das falsch?
Oder brauche ich gar keinen Speicher mehr anzufordern, weil mein Interface zwar PWideChar erwartet, aber in der instanziierten Klasse ein string verwendet wird und somit schon wieder alles in einen eigenen Speicherbereich "kopiert" wird? (Das wäre mir persönlich am allerliebsten)

Ich hoffe ihr habt meine Frage(n) verstanden und könnt mir nochmal weiterhelfen.
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#38

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 11. Okt 2016, 20:10
Ähmmm....ich bin zwar schon einige Zeit raus aus Delphi (fang grad wieder damit an), aber ist das nicht etwas kompliziert und aufwendig ?

Ich würde banalerweise einfach eine Unit machen, die die entsprechenden Record deklarationen enthält,
die sowohl in der DLL, als auch im Programm mit einbinden und dann das ganze ist gelutscht ?


Beispiel:

Code:
Unit SharedTypes;

INTERFACE

TYPE

   pUser = ^TUser;
   TUser = record
              Username : widestring;
              Loginname: widerstring;
              {und was halt noch so rein soll} 
           end
Die Funktionen der DLL geben einfach pUser als Rückgabewert zurück. Und damit kannst du ganz
normal im Hauptprogramm arbeiten....


oder überseh ich da was ?
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#39

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 11. Okt 2016, 20:35
So habe ich es ja aktuell. Nur Blup meinte ja das, wenn man schon mit Interfaces arbeitet, auch gleich alles mit Interfaces machen sollte. Um das mal vereinfacht auszudrücken. So wollte ich das dann machen.

Aktuell habe ich ja alles mit Records aufgebaut. Das funktioniert auch.

Nur würde mich jetzt interessieren wie es mit Interfaces funktioniert wenn ich schon den Vorschlag gemacht bekomme. So ganz habe ich das System noch nicht durchschaut.
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#40

AW: DLL Programmierung - Wie übergebe ich am sinnvollsten meine Daten?

  Alt 12. Okt 2016, 10:49
Mir ist nicht klar warum du mit PWideChar arbeiten willst, aber nicht mit WideString.
In neueren Delphiversionen ist String = UnicodeString definiert. Einer direkten Zuweisung im Setter oder Getter steht da nichts im Wege.
Um die Speicherverwaltung und Typkonvertierung sollte sich Delphi doch eigentlich selbst kümmern?
Delphi-Quellcode:
  IDMSUserExchange = interface(IInterface)
  [GUID]
    function GetUserName: WideString;
    procedure SetUserName(const AValue: WideString);
    property UserName: WideString read GetUserName write SetUserName;
  end;

   TDMSInternalUserData = class(TInterfacedObject, IDMSUserExchange)
   private
     FUserName: string; // <-- Hier string
   protected
{$REGION 'IDMSUserExchange'}
     function GetUserName: WideString;
     procedure SetUserName(const AValue: WideString);
{$ENDREGION}
   end;

implementation
   
function TDMSInternalUserData.GetUserName: WideString;
begin
  Result := FUserName;
end;
 
procedure TDMSInternalUserData.SetUserName(const AValue: WideString);
begin
  FUserName := AValue;
end;

procedure TuWasMitUserData(AUserData: IDMSUserExchange; const AValue: string);
begin
  AUserData.UserName := AValue;
end;
Wenn die Arbeit mit Objekten sein muss, kannst du aber für die Objekte Properties definieren, die andere Typen zur Verfügung stellen als das Interface.
Ich sehe dafür aber keine Notwendigkeit.
Delphi-Quellcode:
   TDMSInternalUserData = class(TInterfacedObject, IDMSUserExchange)
   private
     FUserName: string; // <-- Hier string
   protected
{$REGION 'IDMSUserExchange'}
     function GetUserName: WideString;
     procedure SetUserName(const AValue: WideString);
{$ENDREGION}
   public
     property UserName: string read FUserName write FUserName;
   end;

Geändert von Blup (12. Okt 2016 um 12:32 Uhr) Grund: Interface-Deklaration ergänzt
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 4 von 5   « Erste     234 5      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:06 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