64Bit DLL für VBasic Strings?

Antworten
sn00py_spy
Beiträge: 4
Registriert: Di 2. Nov 2010, 12:00

64Bit DLL für VBasic Strings?

Beitrag von sn00py_spy »

Hallo, hat schon wer einmal versucht / erfolgreich geschafft einen Text aus einer 64Bit Dll an VB zu übergeben?

Ich teste es hier mit Excel 2010, die DECLARE Functions müssen nun mit PTRSafe gekennzeichnet werden
und mir stürzt jedesmal Excel einfach ohne warnung ab

das habe ich schon alles in der DLL versucht :

Code: Alles auswählen

function ResultTestS : PChar; stdcall; export;
begin
     Result          := PChar('TEST4711');
end;
 
function ResultTestS2 : Pointer; stdcall; export;
var
   temp  : string;
begin
     temp  := 'TEST4711';
     Result          := Pointer(@temp[1]);
end;
 
function ResultTestS4(Value : PChar; len : integer) : integer; stdcall; export;
var
    temp  : string;
begin
    temp    := 'TEST4711';
    Result  := length(temp);
 
    ZeroMemory(@Value[1], len);
    CopyMemory(@Value[1], @temp[1], Result);
end;
 
function ResultTestS3 : PChar; stdcall; export;
var
   temp  : string;
begin
     temp  := 'TEST4711';
     Result          := PChar(@temp[1]);
end;


hat noch wer eine idee, was ich alles testen/probieren kann?

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Re: 64Bit DLL für VBasic Strings?

Beitrag von monta »

Ist das ein 64Bit Excel oder könnte da der Fehler liegen, da 64Bit DLLs generell nicht funktionieren?
Johannes

sn00py_spy
Beiträge: 4
Registriert: Di 2. Nov 2010, 12:00

Re: 64Bit DLL für VBasic Strings?

Beitrag von sn00py_spy »

monta hat geschrieben:Ist das ein 64Bit Excel oder könnte da der Fehler liegen, da 64Bit DLLs generell nicht funktionieren?


Ja, es ist ein 64Bit Excel und der rest funktioniert, ich kann integer zurückgegben und Strings in die DLL geben, aber beim zurückgeben von Strings aus der DLL nach Excel 2010 gibts probleme.

Wenn ich für Firebird per UDF einen String zrückgebe, dann darf ich da auch nicht einfach einen PChar aus dem string machen, sondern muß mit einem speziellen "malloc" speicher reservieren und da dann reinkopieren
wahrscheinlich ist es hier auch was ähnliches?

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: 64Bit DLL für VBasic Strings?

Beitrag von mschnell »

Das Interface zwischen einem Programm und einer DLL / SO, die in einer anderen Programmier-Sprache geschrieben ist, muss "flat" sein, da die sprachen unterschiedliche ABI (Application Binary Interface) - Spezifikationen verwenden Für einige unterschiedliche "flat"-ABI Specs von Funktionen gibt es entsprechende Keywords (CDECL, STDCALL, PASCAL), die in vielen Sprachen zur Verfügung stehen,. Natürlich müssen die entsprechenden Funktionen auf beiden Seiten mit derselben flat ABI Spec definiert sein.

Die flat ABI erlaubt nur Standard-Typen, die in ANSI C definiert sind. Also keine Strings und keine Objekte, demzufolge also auch kein gemeinsames Memory-Management. Das Programm kann so direkt Funktionen in der DLL aufrufen. Durch callbacks kann die DLL Funktionalitäten den Hauptprogramms nutzen.

Zu String / pchar:

xpchar := pchar(xstring);
ist richtig (pchar ist keine einfache Typumwandlung)

xpchar := @xstring[1];
ist auch richtig

xpchar := @xstring;
ist falsch


Aber:
Wenn Du in einer Funktion den String anlegst und einen pchar auf den String an den Aufrufer zurückgibst, geht das daneben, weil der String spätestens nach Verlassen der Funktion deallokiert wird (das Reference counting erstreckt sich nicht auf pchars!) und der pchar dann auf nichts sinnvolles mehr zeigt. Das geht nur mit Strings, die außerhalb definiert sind.

-Michael
Zuletzt geändert von mschnell am Sa 6. Nov 2010, 00:51, insgesamt 1-mal geändert.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: 64Bit DLL für VBasic Strings?

Beitrag von Socke »

sn00py_spy hat geschrieben:function ResultTestS2 : Pointer; stdcall; export;
var
temp : string;
begin
temp := 'TEST4711';
Result := Pointer(@temp[1]);
end;
[/code]

Pass auf, wann du einen String als Funktionsergebnis ausgibst. Wie mschnell bereits gesagt hat, gibt es keine gemeinsame Speicherverwaltung. Strings werden vom FPC automatisch freigegeben, wenn keine Referenz mehr vorhanden ist. In dem Beispiel oben hast du Glück, dass temp auf einen konstanten String zeigt, der auch nach dem Verlassen der Funktion noch vorhanden ist.

mschnell hat geschrieben:pchar := @xstring;
ist falsch

@xstring ergibt die Adresse der String-Variablen, die technisch gesehen auch nur ein Zeiger ist; die eigentlichen Nutzdaten liegen bei @xstring[1].
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

marcov
Beiträge: 1100
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: 64Bit DLL für VBasic Strings?

Beitrag von marcov »

Ich dacht VB Strings wuerden meistens Unicode, weil PChar in Lazarus meistens ASCII sind.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: 64Bit DLL für VBasic Strings?

Beitrag von Socke »

-
marcov hat geschrieben:Ich dacht VB Strings wuerden meistens Unicode, weil PChar in Lazarus meistens ASCII sind.

Die Zeichenkodierung der VB Strings ist tatsächlich wichtig.

PChar ist in FreePascal nur ein Zeiger auf Char, 8 Byte. Wenn man das an eine externe Bibliothek weitergibt, wird das in der Regel sogar ein Zeiger auf einen null-terminierten String sein. Ob dieser String in ASCII, ISO 8859-1 oder UTF-8 kodiert ist, hängt beim FPC von der Quelltextkodierung ab. Bei mir ist das mit Lazarus immer UTF-8.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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: 64Bit DLL für VBasic Strings?

Beitrag von mschnell »

marcov hat geschrieben: weil PChar in Lazarus meistens ASCII sind.
Die 128 "ASCII" Codes sind mit den entsprechenden UTF-8 Codes identisch. das wäre also kein Problem. :) Ich vermute, Du meinst aber "ANSI" (256 länderspezifische Codes).

Mit Unicode musst Du natürlich aufpassen! "pchar" ist einfach nur ein Zeiger. Wie die Codierung des Inhalts des Memory-Bereichs ist, auf den er zeigt, hängt einfach nur vom Programmierer ab und muss natürlich zwischen der Applikation und der DLL abgesprochen sein. Quasi immer wird ein pchar als NULL-terminierte Byte-Folge verstanden.

Ich vermute, die Funktion pchar(xString) ändert bei mit 8-Bit codierten Strings (heißen "ANSISTRING", auch wenn sie in Linux bei den neueren Lazarus-Version meist UTF-8 codiert sind) an der Codierung nichts. Ich weiß nicht was pchar (xWideString) macht (würde ich mit Lazarus auch nicht benutzen, da die LCL (auch in Windows) UTF-8 verwendet).

-Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: 64Bit DLL für VBasic Strings?

Beitrag von Socke »

mschnell hat geschrieben:Ich vermute, die Funktion pchar(xString) ändert bei mit 8-Bit codierten Strings (heißen "ANSISTRING", auch wenn sie in Linux bei den neueren Lazarus-Version meist UTF-8 codiert sind) an der Codierung nichts. Ich weiß nicht was pchar (xWideString) macht (würde ich mit Lazarus auch nicht benutzen, da die LCL (auch in Windows) UTF-8 verwendet).

Hab ich gestern nachgelesen: gar nichts, bzw. nur den Zeiger zurückliefern. Es wird keine Konvertierung von Widestring nach UTF-8/Ansistring vorgenommen. Da Widestrings aus WideChars bestehen und diese auch ein (in der Regel das höherwertige) Byte mit dem Wert Null besitzen können, wird ein Widestring mit zwei Null-Bytes terminiert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten