[Megoldva]Delphi és c++ házasítás.

 ( emberk | 2008. június 3., kedd - 11:07 )

Sziasztok.

Ketten dolgozunk egy feladaton, ami egy régebben megírt (és alaposan kituningolt) Delphi kódra épül, na eddig nem is volt baj (itt jöttem én a képbe :D ), ugyanis én eddig csak linux alá írtam programot win alá még soha, ergo a delphiről annyit tudok hogy van, és volt linuxos klónja a kylix de a kutyának nem kellet (azt hiszem 3XX-darabot adtak el belőle 1 év alatt).Na szóval a lényeg, egy elég komoly eszköz vezérlését szeretnénk megoldani, de nagyon sok számítást igénylő mestint progi működteti a vezérlést (Ezt írtam én C-ben). Az egyik részét átkódoltuk delphibe, de annyira lassú lett, hogy használhatatlan(Kb a sebesség az 1/2 1/3-ra esett vissza, biztos nem a lehető legjobb mgolás, mert a kollegám grafikai elemeket kódolt eddig, én meg C + egy minimális asm). Na akkor jött az ötlet, hogy elvileg megoldható az, hogy az én kódomat mint dll-t fordítjuk le, és csak a kimeneti paraméterekt adja meg a delphi kódnak, így gyors maradhat (és nekem sem kell a delphivel vacakolni, pláne hogy nem is működik elegendő sebességgel). De ez sehogy nem akar összejönni. Végignéztem egy rakat tutoriált helpet... Azok közül semmivel nem ment. A delphi vagy azt mondja hogy nem léteő dll, vagy azt hogy a menyitott dll-ben nincs ilyen függvény. Nem másolgatok be azokból amit kiőróbáltam mert van vagy 70, de az eredmény ugyanaz, nem tud valaki valami használható ötletet adni? Ja borland developper studio 2006 vagy mi van nekünk.

Azt tudom, hogy az egyik megoldás a C-ben írt dll-re az ez a fajta deklaráció:
extern "C" __declspec(dllexport) int perforationsenzor (int x1, int x2, int y1, int y2, int erzekenyseg)
{
itt jön a kód.
}
Le is fordul szépen, majd hibaüzenetként kiirja, hogy mivel ez egy dll nem tudjuk használni állítsuk be a run/dialogboban, hogy melyik exe használja, na én ezt az exe-t simán elindítom (manuálisan kintről), de a fenti probléma jön elő.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

delphiben deklarálni kell a függvényedet valahogy így:

function perforationsenzor (x1,x2,y1,y2,erzekenyseg:integer):integer; external 'dllfaljneve.dll';

talán segíthet még a cdecl és/vagy a stdcall kulcsszó...

--
Falu

Igen így van benne. Semmi változás

megnézed "szemmel", hogy egész pontosan hogy is szerepel az a symbol abban a dllben. valami dekoráció miatt nem találja szerintem

Azt hogy kell? Olyan mit a .so vagy .a linuxban? sima editorral ez egy bináris file.

pff... midnight commanderben F3 és search

És tényleg igazad van. Látod _perforationsenzor lett a neve.

A PostgreSql libpq.dll-jében lévő függvényeket így lehet elérni:
Ami telőtte be jkell tölteni!!!!

Definíció

type
  TPQexec          = function(Handle: PPGconn; Query: PChar): PPGresult; cdecl;
  TPQnotifies      = function(Handle: PPGconn): PPGnotify; cdecl;
  TPQfreeNotify    = procedure(Handle: PPGnotify);cdecl;
  TPQsendQuery     = function(Handle: PPGconn; Query: PChar): Integer; cdecl;
  TPQgetResult     = function(Handle: PPGconn): PPGresult; cdecl;
  TPQisBusy        = function(Handle: PPGconn): Integer; cdecl;
  TPQconsumeInput  = function(Handle: PPGconn): Integer; cdecl;
  TPQgetline       = function(Handle: PPGconn; Str: PChar; length: Integer): Integer; cdecl;
  TPQputline       = function(Handle: PPGconn; Str: PChar): Integer; cdecl;
  TPQgetlineAsync  = function(Handle: PPGconn; Buffer: PChar; BufSize: Integer): Integer; cdecl;
  TPQputnbytes     = function(Handle: PPGconn; Buffer: PChar; NBytes: Integer): Integer; cdecl;
  TPQendcopy       = function(Handle: PPGconn): Integer; cdecl;
  TPQfn            = function(Handle: PPGconn; fnid: Integer; result_buf, result_len: PInteger; result_is_int: Integer; args: PPQArgBlock; nargs: Integer): PPGresult; cdecl;
  TPQresultStatus  = function(Result: PPGresult): ExecStatusType; cdecl;
  TPQresultErrorMessage = function(Result: PPGresult): PChar; cdecl;


var
{ ===	in fe-connect.c === }
  PQconnectdb:     TPQconnectdb;
  PQsetdbLogin:    TPQsetdbLogin;
  PQconndefaults:  TPQconndefaults;
  PQfinish:        TPQfinish;
  PQreset:         TPQreset;
  PQrequestCancel: TPQrequestCancel;
  PQdb:            TPQdb;
  PQuser:          TPQuser;
  PQpass:          TPQpass;
  PQhost:          TPQhost;
  PQport:          TPQport;
  PQtty:           TPQtty;
  PQoptions:       TPQoptions;
  PQstatus:        TPQstatus;
  PQerrorMessage:  TPQerrorMessage;
  PQsocket:        TPQsocket;
  PQbackendPID:    TPQbackendPID;
  PQtrace:         TPQtrace;
  PQuntrace:       TPQuntrace;
  PQsetNoticeProcessor: TPQsetNoticeProcessor;

{ === in fe-exec.c === }
  PQexec:          TPQexec;
  PQnotifies:      TPQnotifies;
  PQfreeNotify:    TPQfreeNotify;
  PQsendQuery:     TPQsendQuery;
  PQgetResult:     TPQgetResult;
  PQisBusy:        TPQisBusy;
  PQconsumeInput:  TPQconsumeInput;
  PQgetline:       TPQgetline;
  PQputline:       TPQputline;
  PQgetlineAsync:  TPQgetlineAsync;
  PQputnbytes:     TPQputnbytes;
  PQendcopy:       TPQendcopy;
  PQfn:            TPQfn;
  PQresultStatus:  TPQresultStatus;
  PQresultErrorMessage: TPQresultErrorMessage;
  PQresultErrorField: TPQresultErrorField; //Firmos
  PQntuples:       TPQntuples;
  PQnfields:       TPQnfields;
  PQbinaryTuples:  TPQbinaryTuples;
  PQfname:         TPQfname;
  PQfnumber:       TPQfnumber;
  PQftype:         TPQftype;
  PQfsize:         TPQfsize;
  PQfmod:          TPQfmod;
  PQcmdStatus:     TPQcmdStatus;
  PQoidValue:      TPQoidValue;
  PQoidStatus:     TPQoidStatus;
  PQcmdTuples:     TPQcmdTuples;
  PQgetvalue:      TPQgetvalue;
  PQgetlength:     TPQgetlength;
  PQgetisnull:     TPQgetisnull;
  PQclear:         TPQclear;
  PQmakeEmptyPGresult:  TPQmakeEmptyPGresult;

//FirmOS: New defines
  PQescapeByteaConn:TPQescapeByteaConn;
  PQescapeBytea:TPQescapeBytea;
  PQunescapeBytea:TPQunescapeBytea;
  PQFreemem:TPQFreemem;

{ === in fe-lobj.c === }
  lo_open:         Tlo_open;
  lo_close:        Tlo_close;
  lo_read:         Tlo_read;
  lo_write:        Tlo_write;
  lo_lseek:        Tlo_lseek;
  lo_creat:        Tlo_creat;
  lo_tell:         Tlo_tell;
  lo_unlink:       Tlo_unlink;
  lo_import:       Tlo_import;
  lo_export:       Tlo_export;

A betöltő ős osztály:

function TZNativeLibraryLoader.LoadNativeLibrary: Boolean;
var
  I: Integer;
  Location: string;
  TriedLocations: string;
begin
  Loaded := False;
  Location := '';
  TriedLocations := '';
  if Handle = 0 then
  begin
    for I := 0 to High(FLocations) do
    begin
      Location := FLocations[I];
//      Handle := GetModuleHandle(PChar(Location));
//      if Handle = 0 then
//      begin
{$IFDEF UNIX}
  {$IFDEF FPC}
        Handle := LoadLibrary(PChar(Location));
  {$ELSE}
        Handle := HMODULE(dlopen(PChar(Location), RTLD_GLOBAL));
  {$ENDIF}
{$ELSE}
        Handle := LoadLibrary(PChar(Location));
{$ENDIF}
//      end;
      if Handle <> 0 then
      begin
        Loaded := True;
        Break;
      end;
      if TriedLocations <> '' then
        TriedLocations := TriedLocations + ', ';
      TriedLocations := TriedLocations + Location;
    end;
  end;

  if not Loaded then
    raise Exception.Create(Format(SLibraryNotFound, [TriedLocations]));
  Result := True;
end;

Betöltés

{**
  Loads a library module.
  @return <code>True</code> if library was successfully loaded.
}
function TZPostgreSQLNativeLibraryLoader.Load: Boolean;
begin
  Result := inherited Load;

{ ===	in fe-connect.c === }
  @PQfreemem           := GetAddress('PQfreemem');
  @PQescapeByteaConn   := GetAddress('PQescapeByteaConn');
  @PQescapeBytea       := GetAddress('PQescapeBytea');
  @PQunescapeBytea     := GetAddress('PQunescapeBytea');

  @PQconnectdb    := GetAddress('PQconnectdb');
  @PQsetdbLogin   := GetAddress('PQsetdbLogin');
  @PQconndefaults := GetAddress('PQconndefaults');
  @PQfinish       := GetAddress('PQfinish');
  @PQreset        := GetAddress('PQreset');
  @PQrequestCancel := GetAddress('PQrequestCancel');
  @PQdb           := GetAddress('PQdb');
  @PQuser         := GetAddress('PQuser');
  @PQpass         := GetAddress('PQpass');
  @PQhost         := GetAddress('PQhost');
  @PQport         := GetAddress('PQport');
  @PQtty          := GetAddress('PQtty');
  @PQoptions      := GetAddress('PQoptions');
  @PQstatus       := GetAddress('PQstatus');
  @PQerrorMessage := GetAddress('PQerrorMessage');
  @PQsocket       := GetAddress('PQsocket');
  @PQbackendPID   := GetAddress('PQbackendPID');
  @PQtrace        := GetAddress('PQtrace');
  @PQuntrace      := GetAddress('PQuntrace');
  @PQsetNoticeProcessor := GetAddress('PQsetNoticeProcessor');

{ === in fe-exec.c === }
  @PQexec         := GetAddress('PQexec');
  @PQnotifies     := GetAddress('PQnotifies');
  @PQfreeNotify   := GetAddress('PQfreeNotify');
  @PQsendQuery    := GetAddress('PQsendQuery');
  @PQgetResult    := GetAddress('PQgetResult');
  @PQisBusy       := GetAddress('PQisBusy');
  @PQconsumeInput := GetAddress('PQconsumeInput');
  @PQgetline      := GetAddress('PQgetline');
  @PQputline      := GetAddress('PQputline');
  @PQgetlineAsync := GetAddress('PQgetlineAsync');
  @PQputnbytes    := GetAddress('PQputnbytes');
  @PQendcopy      := GetAddress('PQendcopy');
  @PQfn           := GetAddress('PQfn');
  @PQresultStatus := GetAddress('PQresultStatus');
  @PQresultErrorMessage := GetAddress('PQresultErrorMessage');
  @PQresultErrorField := GetAddress('PQresultErrorField');
  @PQntuples      := GetAddress('PQntuples');
  @PQnfields      := GetAddress('PQnfields');
  @PQbinaryTuples := GetAddress('PQbinaryTuples');
  @PQfname        := GetAddress('PQfname');
  @PQfnumber      := GetAddress('PQfnumber');
  @PQftype        := GetAddress('PQftype');
  @PQfsize        := GetAddress('PQfsize');
  @PQfmod         := GetAddress('PQfmod');
  @PQcmdStatus    := GetAddress('PQcmdStatus');
  @PQoidValue     := GetAddress('PQoidValue');
  @PQoidStatus    := GetAddress('PQoidStatus');
  @PQcmdTuples    := GetAddress('PQcmdTuples');
  @PQgetvalue     := GetAddress('PQgetvalue');
  @PQgetlength    := GetAddress('PQgetlength');
  @PQgetisnull    := GetAddress('PQgetisnull');
  @PQclear        := GetAddress('PQclear');
  @PQmakeEmptyPGresult := GetAddress('PQmakeEmptyPGresult');

{ === in fe-lobj.c === }
  @lo_open        := GetAddress('lo_open');
  @lo_close       := GetAddress('lo_close');
  @lo_read        := GetAddress('lo_read');
  @lo_write       := GetAddress('lo_write');
  @lo_lseek       := GetAddress('lo_lseek');
  @lo_creat       := GetAddress('lo_creat');
  @lo_tell        := GetAddress('lo_tell');
  @lo_unlink      := GetAddress('lo_unlink');
  @lo_import      := GetAddress('lo_import');
  @lo_export      := GetAddress('lo_export');
end;

initialization
{$IFNDEF UNIX}
  LibraryLoader := TZPostgreSQLNativeLibraryLoader.Create(
    [WINDOWS1_DLL_LOCATION
{$IFNDEF STRICT_DLL_LOADING}
    , WINDOWS2_DLL_LOCATION
{$ENDIF}
    ]);
{$ELSE}
  LibraryLoader := TZPostgreSQLNativeLibraryLoader.Create([LINUX1_DLL_LOCATION,LINUX2_DLL_LOCATION]);
{$ENDIF}
finalization
  if Assigned(LibraryLoader) then
    LibraryLoader.Free;
end.

Attila, Perger
-----------------------------------------------------
"Az a szoftver, amelyiket nem fejlesztik, az halott!"

Én erősen ajvaslom, hogy Delphiből használjátok a LoadLibrary("tecuccod.dll"); hívást, illetve a proc-ok bemeléséhez a GetProcAddress() -t.
Ez ezért lesz jó nektek, mert ha a C -s dll-edet újrafordítot, nem kell a Delphi-s programot is újrafordítani.
Hova tudnék felölteni egy kis példa-csomagot? :)