Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C Funktion, um zwei Strings zu verbinden in DLL (https://www.delphipraxis.net/75245-c-funktion-um-zwei-strings-zu-verbinden-dll.html)

Luckie 16. Aug 2006 14:09


C Funktion, um zwei Strings zu verbinden in DLL
 
Zur Übung versuche ich gerade eine DLL in C zu schreiben, die mir zwei Strings verbindet und diese dann aus einem Delphi-Programm zu nutzen. Ich mache das erstmal mit dem VC2005, weil ich im Moment mit dem GCC und Eclipse nicht weiterkomme.

Meine C-Funktion in der DLL sieht so aus:
Code:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer)
{   
    strcat(str1, str2);
   strcpy(buffer, str1);   
   return strlen(buffer);
}
Der Delphi Code dazu:
Delphi-Quellcode:
type
  TAdd = function(a, b: Integer): Integer; stdcall;
  TAddStr = function(str1, str2: PChar; var Buffer: PChar): Integer; stdcall;

procedure TForm1.Button1Click(Sender: TObject);
var
  hLib: THandle;
  s: String;
  Add: TAdd;
  AddStr: TAddStr;
  res: Integer;
  str1, str2: String;
  Buffer: PChar;
begin
  s := IncludeTrailingBackSlash(ExtractFilePath(ParamStr(0)))+ 'FirstDLL.dll';
  hLib := LoadLibrary(PChar(s));
  if hLib <> 0 then
  begin
    @Add := GetProcAddress(hLib, 'add');
    if Assigned(Add) then
    begin
       res := Add(40, 2);
       ShowMessage(IntToStr(res));
    end
    else
      ShowMessage(SysErrorMessage(GetLastError));

    @AddStr := GetProcAddress(hLib, 'addstr');
    if Assigned(AddStr) then
    begin
      str1 := 'Hello ';
      str2 := 'World';
      GetMem(Buffer, length(str1) + length(str2));
      try
        res := AddStr(PChar(str1), PChar(str2), Buffer);
        ShowMessage(string(Buffer));
      finally
        FreeMem(Buffer);
      end;
    end
    else
      ShowMessage(SysErrorMessage(GetLastError));
    FreeLibrary(hLib);
  end
  else
    ShowMessage(SysErrorMessage(GetLastError));
end;
Aber ich bekomme in der DLL eine AccessViolation.

NicoDE 16. Aug 2006 14:15

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Zitat:

Zitat von Luckie
extern "C" EXPORT

Kannst du dir sparen wenn du eine DEF-Datei verwendest (EXPORTS).
Fehlt da nicht noch ein __stdcall, oder ist der Compiler so konfiguriert, dass es die Standardaufrufkonvention ist?

ps: das 'var' vor Buffer ist zuviel.

Der_Unwissende 16. Aug 2006 14:20

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Hi,
hast du es mal mit _fstrcat versucht? Könnte in deinem Fall sonst ein mögliches Problem werden. Bin nicht C-Crack genug um das hier mit Sicherheit sagen zu können, aber es gab ja Zeiten, in denen man ohne far-Pointer nur im Bereich von 64? KByte die Adressen haben durfte, bei einem Aufruf einer Dll kann das natürlich weniger garantiert werden.

Gruß Der Unwissende

Luckie 16. Aug 2006 14:21

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Wo kommt das __stdcall hin? Wenn ich es so mache:
Code:
extern "C" EXPORT int __stdcall addstr(char *str1, char *str2, char *buffer)
Dann habe ich wieder das name mangling. Eine DEF Datei verwende ich nicht, deswegen das extern "C".

Hm, bei API Funktionen macht man das aber doch auch so mit dem var in Delphi oder?

NicoDE 16. Aug 2006 14:25

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Zitat:

Zitat von Luckie
Dann habe ich wieder das name mangling. Eine DEF Datei verwende ich nicht, deswegen das extern "C".

Name Mangling hast du so oder so (ob nun _foo oder _foo@x ist doch egal).
Nimm eine DEF.

Zitat:

Zitat von Luckie
Hm, bei API Funktionen macht man das aber doch auch so mit dem var in Delphi oder?

*char ist ein PAnsiChar, keine Referefenz auf eine PAnsiChar-Variable.

Luckie 16. Aug 2006 14:29

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Wie geht das mit der DEF Datei? Wo muss die hin in dem VC2005 Projektpfad? Und was muss in ihr drinen stehen? Und muss ich dem VC25005 noch irgendwie sagen, dass er die DEF-Datei verwenden soll?

Zitat:

*char ist ein PAnsiChar, keine Referefenz auf eine PAnsiChar-Variable.
Wie machen denn das API Funktionen?

Flocke 16. Aug 2006 14:45

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Zitat:

Zitat von Luckie
Meine C-Funktion in der DLL sieht so aus:
Code:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer)
{   
    strcat(str1, str2);
   strcpy(buffer, str1);   
   return strlen(buffer);
}

Zitat:

Zitat von Luckie
Aber ich bekomme in der DLL eine AccessViolation.

Das liegt wohl daran, dass du dir in C "str1" überschreibst. Richtiger wäre:
Code:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer)
{   
    strcpy(buffer, str1);   
    strcat(buffer, str2);
    return strlen(buffer);
}

Luckie 16. Aug 2006 14:57

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Yippieyeaho. Es geht. :firejump:

Also als erstes __stdcall in den Projektoptionen eingestellt. Dann eine DEFF-Datei erstellt:
Code:
LIBRARY FirstDLL.dll

EXPORTS
   add
   addstr
Diese dem Linker bekannt gemacht: /DEF:FirstDLL.DEF und kompiliert. Rausgekommen ist eine DLL mit nicht dekorierten Funktionsnamen. Aufrugf von Delphi, wie gehabt ohne das var in der Funktionsdeklaration. Puh, jetzt kan ich auch Feierabend machen. ;)

Drei Dinge noch:
Wie machen das API-Funktionen, dass man da in Delphi das Schlüsselwort var benutzen muss.
Wie sicher ist die C-Funktion bezüglich BufferOverflows?
Und zu guter letzt, wie muss ich es machen, damit meine C-Funktion die erforderliche Größe des Buffers zurückgibt, falls dieser zu klein ist beim Aufruf?

Dax 16. Aug 2006 15:12

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Zitat:

Zitat von Luckie
Wie machen das API-Funktionen, dass man da in Delphi das Schlüsselwort var benutzen muss.

Delphi:
Delphi-Quellcode:
function Foo(var c: Cardinal): Cardinal;
C:
Code:
DWORD Foo(PDWORD c);
Sprich: Delphi macht var-Parameter implizit zu Pointern. Deswegen kann man vielen API-Funktionen, die irgendwas mit Records zu tun haben, diese direkt übergeben, ohne wie in C erst einen Pointer draus machen zu müssen.

Luckie 16. Aug 2006 15:14

Re: C Funktion, um zwei Strings zu verbinden in DLL
 
Aha. Bleiben noch Fragen zwei und drei. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:25 Uhr.
Seite 1 von 3  1 23      

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