Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   C++ C++ builder / DELPHI DLL - Übergabe von String (https://www.delphipraxis.net/190657-c-builder-delphi-dll-uebergabe-von-string.html)

bernhard_LA 23. Okt 2016 08:55


C++ builder / DELPHI DLL - Übergabe von String
 
ich will Teile unserer Delphi Anwendung von einem C++ Modul aus nutzen , hierzu soll nun Delphi Code via DLL verwendet werden . Wir wollen ohne sharemem die Daten (Strings) austauschen.


der Code in der DLL sieht wie folgt aus

Delphi-Quellcode:
var aDatabase : TDatabase;

function Database_create ( server, database, objecttablename, libtablename: PChar; bufsvr, bufdb, bufobj, buflib : Word) : Pointer; stdcall;
begin

  aDatabase:= TDatabase.create(String(server), String(database),
    String(objecttablename), String(libtablename));

  result := aDatabase;
end;


function Database_ElementCount : Integer ;
begin
  result := aDatabase.ElementCount;
end;
zum Testen der DLL gibt es eine kleine Delphi Anwendung

Delphi-Quellcode:

///  Definition Funktion aus DLL
function Database_create(server, database, objecttablename,
  libtablename: PChar; bufsvr, bufdb, bufobj, buflib: Word): Pointer; stdcall;
  external 'databaseDLL.dll';


procedure TForm_database_create_DLLClick
  (Sender: TObject);
var
  server, database, objecttablename, libtablename: string;
begin
  server := lbledt_server.Text;
  database := lbledt_database.Text;
  objecttablename := 'table_name1';
  libtablename := 'tablename2';

  Database_create(PChar(server), PChar(database),
    PChar(objecttablename), PChar(libtablename), length(server),
    length(database), length(objecttablename), length(libtablename));

end;

ich kann mich auf die Datenbank verbinden und Daten lesen / schreiben, alles scheint zu funktionieren.

Nun der Versuch diese ´Datenbank auch via C++ Builder / DLL anzusprechen

in der Header Datei die Definition der Funktiosnprototypen


Delphi-Quellcode:
   
        VoidIn_IntOut Database_ElementCount ;
   StrStrStrStrIn_VoidOut  Database_create;
in dann in der *.cpp Datei dann die eigentliche Implementierung

Delphi-Quellcode:

extern "C" __declspec(dllimport)
   StrStrStrStrIn_VoidOut __stdcall Database_create(char*, char*,
   char*, char*, int, int, int, int);





Database_create = (StrStrStrStrIn_VoidOut)::GetProcAddress
         (load, "Database_create");





void __fastcall TForm1::btn_create_classClick(TObject *Sender) {
   char* server = "localhost\\sqlexpress";
   char* database = "mydatabasetest";
   char* obj = "table1";
   char* lib = "table2";

   Database_create(server, database, obj, lib, 0, 0, 0, 0);
}



hierzu nun meine fragen

a) den Zeiger auf die in der DLL erzeugt Datenbank Klasse lasse ich beim Delphi Testprogramm "undefiniert", ist dies ein Fehler ?
b) der eigentlich Fehler liegt aber in der Umwandlung von PChar im Delphi Code nach Char* im C++ code. Alles als PAnsiChar zu deinieren hat aber leider auch nicht geholfen.


Was mache ich also falsch ?

Ergänzung :

C++ Builder und Delphi XE 2 , alles x32

t.roller 23. Okt 2016 11:28

AW: C++ builder / DELPHI DLL - Übergabe von String
 
In DELPHI entspricht z.B
array [0..99] of Char;

einem String in C++
String[100];

Blup 2. Nov 2016 09:23

AW: C++ builder / DELPHI DLL - Übergabe von String
 
Zitat:

Delphi-Quellcode:
  aDatabase:= TDatabase.create(String(server), String(database),
    String(objecttablename), String(libtablename));

Der harte Cast auf String weist den Compiler an, die Pointer als String zu behandeln. Es findet aber keine Typkonvertierung statt.
Beim Aufrug aus Delphi funktioniert das, da die übergebenen PChar tatsächlich auf existierende Strings verweisen.

Um den Compiler anzuweisen eine Typkonvertierung durchzuführen gibt es verschiedene Wege.

StrPas statt String verwenden, der Compiler erstellt temporäre lokale Variablen selbst:
Delphi-Quellcode:
  aDatabase:= TDatabase.create(StrPas(server), StrPas(database),
    StrPas(objecttablename), StrPas(libtablename));
Selbst lokale Variablen verwenden:
Delphi-Quellcode:
var
  lServer, lDatabase, lObjectTablename, lLibTablename: string;
begin
  lServer := server;
  lDatabase := database;
  lObjectTablename := objecttablename;
  lLibTablename := libtablename
  Result := TDatabase.Create(lServer, lDatabase, lObjectTablename, lLibTablename);
Die Typekonvertierung der Parameter durch Funktionsaufruf:
Delphi-Quellcode:
function _Database_create (const server, database, objecttablename, libtablename: string; bufsvr, bufdb, bufobj, buflib : Word) : TDatabase;
begin
  Result := TDatabase.create(server, database, objecttablename, libtablename);
end;

function Database_create ( server, database, objecttablename, libtablename: PChar; bufsvr, bufdb, bufobj, buflib : Word) : Pointer; stdcall;
begin
  Result := _Database_create(server, database,
    objecttablename, libtablename);
end;

himitsu 2. Nov 2016 10:59

AW: C++ builder / DELPHI DLL - Übergabe von String
 
Und ein "dynamisches" PChar in einer Schnittstelle? (DLL)

Dafür sollte man gleich gerädert und gevierteilt werden.



Man darf NIEMALS NIE dynamische Typen in für Importe/Exporte verwenden.

PAnsiChar und PWideChar blieben vor 2009 und ab 2009 gleich und auch Sprachübergreifend sind sie gleich.
Char/PChar können sich dagegen schonmal unterscheigen ... Es wäre doch blöd, wenn EXE und DLL da nicht das Selbe nutzen? :roll:


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:41 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