Autor Beitrag
crxfreak
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 20.04.07 10:09 
Hallo in die Runde,

ich habe eine Access.dll auf die ich mit einem VB-Programm zugreifen muß.
Nachfolgend der Code mit dem über Delphi auf die DLL zugegriffen wird.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
program ea;
{$APPTYPE CONSOLE}
uses
  SysUtils, Windows;

  const
    LibName = 'Access.dll';
  var
    HLib : THandle;

  type
    TGetUGfsPGfs = function (FileName : PChar; var UGfs, PGfs : DWORD) : integer; cdecl;
    TGetErrorStr = function  : PChar; cdecl;
    TGetVersionNr = function : integer; cdecl;
  var
    GetUGfsPGfs : TGetUGfsPGfs;
    GetErrorStr : TGetErrorStr;
    GetVersionNr : TGetVersionNr;

    UGfs, PGfs : DWORD;

  function DWORDToStr(x : DWORD) : string;
    var
      i : integer;
      Mask : DWORD;
  begin
    Result := '';
    Mask := 1;
    for i := 1 to 32 do begin
      if (Mask and x) <> 0 then
        Result := Result + ' ' + IntToStr(i);
      Mask := Mask shl 1;
    end {for};
  end {DWORDToStr};

begin
  // Insert user code here
  if ParamCount = 0 then begin
    Writeln(Format('Test eds access dll (%s)', [LibName]));
    Writeln('Usage: ea filename');
  end else begin
    try
      HLib := LoadLibrary(PChar(LibName));
      try
        if HLib = THandle(0) then
          raise Exception.Create(Format('Cannot open %s', [LibName]));

        // Extract the required routines
        GetUGfsPGfs := GetProcAddress(HLib, 'GetUGfsPGfs');
        if not Assigned(GetUGfsPGfs) then
          raise Exception.Create('GetUGfsPGfs not found');

        GetErrorStr := GetProcAddress(HLib, 'GetErrorStr');
        if not Assigned(GetErrorStr) then
          raise Exception.Create('GetErrorStr not found');

        GetVersionNr := GetProcAddress(HLib, 'GetVersionNr');
        if not Assigned(GetVersionNr) then
          raise Exception.Create('GetVersionNr not found');

        // Show lib version nr
        Writeln(Format('Lib version Nr: %d', [GetVersionNr]));

        if GetUGfsPGfs(PChar(ParamStr(1)), UGfs, PGfs) = 1 then begin
          Writeln(Format('UGfs: %s', [DWORDToStr(UGfs)]));
          Writeln(Format('PGfs: %s', [DWORDToStr(PGfs)]));
        end else
          raise Exception.Create(StrPas(GetErrorStr));

      finally
        FreeLibrary(HLib);
      end {try};
    except
      on E: Exception do begin
        Writeln('*** ' + E.Message);
      end;
    end {try}
  end {if};
end.


Unter VB habe ich die DLL folgendermaßen deklariert...
Zitat:
Private Declare Sub GetUGfsPGfs Lib "ACCESS.DLL" (ByRef File As String, ByRef SvrToMacUGfs As Long, ByRef SvrToMacPGfs As Long)

Wenn ich die Werte an die DLL nach folgendem Schema übergebe...
Zitat:
GetUGfsPGfs Dateiname$, Ugfs, Pgfs

erhalte ich immer die Meldung "Laufzeitfehler '49': Falsche DLL-Aufrufkonvention"

Ich habe schon alle möglichen Datentypen für Ugfs und Pgfs probiert. Hat jemand noch eine Idee für mich?
ene
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 779
Erhaltene Danke: 1

Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
BeitragVerfasst: Fr 20.04.07 10:21 
Hi,

wenns ne Sub ist, sollte es so besser sein:

ausblenden Quelltext
1:
GetUGfsPGfs(Dateiname$, Ugfs, Pgfs)					


Vielleicht hilft ein Call davor auch noch. Und du arbeitest hoffentlich im gleichen Modul, sonst wärs als Public ganz nett. Und Sonderzeichen würde ich lieber weglassen.

_________________
Wir, die guten Willens sind, geführt von Ahnungslosen, Versuchen für die Undankbaren das Unmögliche zu vollbringen.
Wir haben soviel mit so wenig so lange versucht, daß wir jetzt qualifiziert sind, fast alles mit Nichts zu bewerkstelligen.
crxfreak Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 20.04.07 10:28 
Danke erstmal für die Antwort.

ausblenden Delphi-Quelltext
1:
Call GetUGfsPGfs(Dateiname$, Ugfs, Pgfs)					

bringt leider nichts - selber Fehler.

Ja, ist alles in ein und der selben form.
ene
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 779
Erhaltene Danke: 1

Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
BeitragVerfasst: Fr 20.04.07 11:04 
Mach mal bitte eine Funktion draus, mit Subs habe ich in diesem Zusammenhang noch nicht gearbeitet.

_________________
Wir, die guten Willens sind, geführt von Ahnungslosen, Versuchen für die Undankbaren das Unmögliche zu vollbringen.
Wir haben soviel mit so wenig so lange versucht, daß wir jetzt qualifiziert sind, fast alles mit Nichts zu bewerkstelligen.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Fr 20.04.07 11:11 
Die Fehlermeldung ist doch klar und eindeutig: Die Aufrufkonvention der Delphi-DLL ist nicht mit VB kompatibel. Schreib ein 'safecall' (glaub ich) hinter die Prozedurdeklaration in der DLL, so etwa:

ausblenden Delphi-Quelltext
1:
Procedure Foobar (Foo : String); safecall					


Außerdem würde ich mit OleVariants arbeiten, bei Strings würde ich nicht die Hand ins Feuer legen, das das auch klappt.

@ene: Prozeduren/SUBs klappen. Das Funktionen auch gehen, wusste ich nicht :lol:

_________________
Na denn, dann. Bis dann, denn.
ene
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 779
Erhaltene Danke: 1

Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
BeitragVerfasst: Fr 20.04.07 11:21 
Wenn man eine DLL hat, die einem auch was zurückgibt, gehts ja nicht anders als über eine Funktion. Und wenn sich etwas nicht mit VB steuern läßt, muss man halt andere Wege gehen.

_________________
Wir, die guten Willens sind, geführt von Ahnungslosen, Versuchen für die Undankbaren das Unmögliche zu vollbringen.
Wir haben soviel mit so wenig so lange versucht, daß wir jetzt qualifiziert sind, fast alles mit Nichts zu bewerkstelligen.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Fr 20.04.07 12:13 
user profile iconene hat folgendes geschrieben:
Wenn man eine DLL hat, die einem auch was zurückgibt, gehts ja nicht anders als über eine Funktion. Und wenn sich etwas nicht mit VB steuern läßt, muss man halt andere Wege gehen.

ausblenden Delphi-Quelltext
1:
Procedure FooBar (VAR Rueckgabe : OleVariant);					

:gruebel:

[edit] hab gerade gesehen, das die Delphi-DLL ja Funktionen deklariert, dann muss natürlich das VB-pendant auch eine Funktion sein [/edit]

_________________
Na denn, dann. Bis dann, denn.
ene
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 779
Erhaltene Danke: 1

Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
BeitragVerfasst: Fr 20.04.07 12:27 
Find ich "bäh" ;) Eine Prozedur hat keinen Rückgabeparameter und eine Funktion genau einen. Alles andere wird über Variablen geregelt, aber das ist schon mehr eine philosophische Frage.

_________________
Wir, die guten Willens sind, geführt von Ahnungslosen, Versuchen für die Undankbaren das Unmögliche zu vollbringen.
Wir haben soviel mit so wenig so lange versucht, daß wir jetzt qualifiziert sind, fast alles mit Nichts zu bewerkstelligen.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Fr 20.04.07 12:33 
user profile iconene hat folgendes geschrieben:
Find ich "bäh" ;) Eine Prozedur hat keinen Rückgabeparameter

Was?
user profile iconene hat folgendes geschrieben:
und eine Funktion genau einen. Alles andere wird über Variablen geregelt, aber das ist schon mehr eine philosophische Frage.

Äh.. Variablen? Du meinst dochg sicherlich VAR Parameter, alles andere wäre 'bäh'? Aber wenn es genau ein Rückgabewert ist, hast Du natürlich Recht, da nehme ich dann auch eine Funktion. Ehrlich gesagt wusste ich nicht, das auch Funktionsaufrufe kompatibel sind (zwischen VB, Delphi, C etc.), wenn es nicht gerade um Basistypen geht.

_________________
Na denn, dann. Bis dann, denn.
crxfreak Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 20.04.07 12:43 
Ich bin noch über einen Beitrag gestolpert...

pscode.com/vb/script...d=49776&lngWId=1

Offensichtlich werden werden C - DLLs nicht richtig von VB unterstützt.
Hat da jemand schonmal was von gehört - ich arbeite zum ersten mal mit VB und C, sonst immer mit VB + Cobol.

Hier noch der kurze Erklärungstext den ich erhalten habe...
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
The test application uses run-time dynamic linking.
 
You will have to implement this in your application:
 
DWORD SvrToMacUGfs = 0;
DWORD SvrToMacPGfs = 0;
DWORD U,P;
 
for each file listed in the SvrToMac file
{
  GetUGfsPGfs(edsfilename, U, P);
  SvrToMacUGfs |= U;
  SvrToMacPGfs |= P;
}
ene
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 779
Erhaltene Danke: 1

Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
BeitragVerfasst: Fr 20.04.07 12:44 
Ist halt philosophisch und solange man nicht gerade mit NullStrings arbeitet, macht auch VB i.d.R. mit. Meine DLL ist nur für die Steuerung einer Zählerkarte und da gibts neben der Initialisierung und dem Kill nur 1 Wert, den ich auslesen will und die anderen beiden sind Bool. Aber nun genug Philosophie ;)

_________________
Wir, die guten Willens sind, geführt von Ahnungslosen, Versuchen für die Undankbaren das Unmögliche zu vollbringen.
Wir haben soviel mit so wenig so lange versucht, daß wir jetzt qualifiziert sind, fast alles mit Nichts zu bewerkstelligen.
crxfreak Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 20.04.07 13:25 
ähm Nullstrings...

Hab ich ganz vergessen mit rein zuschreiben.

Zitat:

Access dll interface
-----------------------
The Access dll allows to read the UGfs and PGfs values of a specified EDS file.
The library exports 3 routines.

GetUGfsPGfs
-----------

The GetUGfsPGfs function reads the UGfs and PGfs values out of a specified
file.

int __cdecl GetUGfsPGfs(LPSTR FileName, PDWORD UGfs, PDWORD PGfs);

Parameters:

FileName [in] pointer to a null terminated string with the file name.
UGfs [out] pointer to a DWORD to receive the UGfs value
PGfs [out] pointer to a DWORD to receive the PGfs value

Return value:

The function returns 1 if ok else it returns 0.


GetErrorStr
-----------

The GetErrorStr function retrievs the latest error string. Call GetErrorStr
when GetUGfsPGfs returns 0.

LPSTR __cdecl GetErrorStr(void);

The return value is a pointer to a null terminated error string.


GetVersionNr
------------

The GetVersionNr function returns the Dll version Nr.

int __cdecl GetVersionNr(void);