Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Parameterübergabe an externe DLL (Pointer, Array, u.s.w.) (https://www.delphipraxis.net/154879-parameteruebergabe-externe-dll-pointer-array-u-s-w.html)

dust258 29. Sep 2010 10:58


Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Hallo Leute,
seit ein paar Tagen versuche ich eine Externe DLL in mein Programm einzubinden. Der Quellcode der Dll liegt zwar nicht vor, dafür aber Programmierbeispiele in C# und c. Die DLL wandelt die Daten um und gibt sie dann an eine Java-Applikation weiter.
Das Einbinden hat auch schon ganz gut funktioniert, nur die Parameterübergabe macht mir noch einige Probleme...

Es wird ein ein Array der Struktur "Document" erwartet ;
Code:
   struct Document //verkleinerte Version
   {
      public int   version;
      public string FileName;
      public IntPtr data;
      public int dataLen;
}
Also in Delphi:
Delphi-Quellcode:
type
  TDocument = packed record
      version : Integer;
      FileName : PChar;
      data : Pointer;
      dataLen : Integer;
  end;
Mit "data" wird ein Pointer auf ByteArray (Byte[]), das die zu bearbeitende Datei enthält, übergeben.

Code:
                  FileStream fileStream = new FileStream("c:/test.pdf", FileMode.Open, FileAccess.Read);
                  BinaryReader fileReader = new BinaryReader(fileStream);

                  byte[] contentBuffer = fileReader.ReadBytes(1500000);
                  fileReader.Close();

                  IntPtr contentCBuffer = Marshal.AllocHGlobal(contentBuffer.Length);
                  Marshal.Copy(contentBuffer, 0, contentCBuffer, contentBuffer.Length);

                  documents[i].version = 6;
                  documents[i].documentFileName = "test.pdf";
                  documents[i].dataToBeSigned = contentCBuffer;
                  documents[i].dataToBeSignedLen = contentBuffer.Length;
Mein Typ um ein Byte[] zu simulieren:
Delphi-Quellcode:
type
  TArrayOfByte = Array of Byte;
  PArrayOfByte = ^TArrayOfByte;
Und der Aufruf
Delphi-Quellcode:
var
  len : Integer;
  FileStream : TFileStream;
  BArrcontentBuffer : TArrayOfByte;
  PBArrContentBuffer : PArrayOfByte;
begin
    documents[i].version := 6;
    documents[i].FileName := PCHar('test.pdf');

    FileStream := TFileStream.Create('c:\test.pdf', fmOpenRead);
    try
      len := FileStream.Size;
      SetLength(BArrcontentBuffer, len);
      FileStream.ReadBuffer(Pointer(BArrcontentBuffer)^, len);
      PBArrContentBuffer := @BArrcontentBuffer;
    finally
      FileStream.Free;
    end;

    documents[i].dataToBeSigned := PBArrContentBuffer; //wenn ich hier einen Haltepunkt setzt enthält PBArrContentBuffer die gleichen Daten wie in meinem C# Beispielprogramm
    documents[i].dataToBeSignedLen := len;
end;

Meine Frage:
Die Dll liefert mir im Moment folgende Fehlermeldung (über eine Funktion GetLastErrorMessage):
Zitat:

SecSignerAdapter.signMulti failed: java.lang.NullPointerException: DataToSign not defined
at seccommerce.secsignersigg.lo.a(Unknown Source)
at seccommerce.secsignersigg.lp.a(Unknown Source)
at seccommerce.secsignersigg.lh.a(Unknown Source)
at seccommerce.secsignersigg.SecSigner.sign(Unknown Source)
at seccommerce.secsigner.ext.SecSignerAdapter.signMul ti(Unknown Source)
Seht Ihr was ich da falsch mache? Wenn ich einen Haltepunkt auf PBArrContentBuffer sind die gleichen Daten vorhanden wie im c# Programm

Das ist das 1. mal das ich mit einer dll in Delphi arbeite. Ich hoffe da kann mir Jemand helfen. Danke für die Mühe ^^

PS: Tipps, Anmerkungen, Fragen? Immer her damit.

dust258 30. Sep 2010 09:33

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Ich habe die Frage noch einmal zusammengefasst. Ich hoffe jetzt ist es ein wenig leichter zu lesen...

dust258 4. Okt 2010 14:30

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Ich habe jetzt auch den in C geschriebenen Beispielcode zum laufen bekommen. Seht Ihr eine Möglichkeit (unsigned char*)malloc in Delphi nachzustellen?

Struktur aus der Header-Datei:
Code:
typedef struct
{
   int   version;      
   char* documentFileName;      
   unsigned char* dataToBeSigned;  
   int dataToBeSignedLen;
}
Pointer sign()
Code:
SIGN = (SIGN_TYPE) GetProcAddress(hMod, "SecSigner_Sign");


int signDocs(DOCUMENT documents[], int documentCount,
          BYTEARRAY cipherCerts[], int cipherCertCount,
          BYTEARRAY softKeyData[], int softKeyDataCount)
{
   int ret = (*SIGN)(documents, documentCount, cipherCerts, cipherCertCount, softKeyData, softKeyDataCount);
   

   return ret;
}
Und der Aufruf:
Code:
contentBuffer = (unsigned char*)malloc(CONTENT_BUF_LEN);

            filePos = 0;
            while (true)
            {
               int bytesRead = _read(fd, &contentBuffer[filePos], CONTENT_BUF_LEN-filePos);
         
               if (bytesRead < 0)
               {
                  return -1;
               }

               if (bytesRead == 0)
               {
                  break;
               }
   
               filePos+=bytesRead;
            }

            documents[i].version = 7;
            documents[i].documentFileName = "test.pdf";
            documents[i].dataToBeSigned = contentBuffer;
            documents[i].dataToBeSignedLen = filePos;
EDIT: Die DLL wurde übrigens in C++ geschrieben.

Zacherl 4. Okt 2010 14:40

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Wenn ich mich nicht irre müsste unsigned char* das selbe wie ein PChar sein. Du könntest also mit SetLength() ein dynamisches array of Char alloziieren und @Array[0] als Pointer für das Struct benutzen. Dann aber beim reinkopieren der Daten (das Strings) an die Nullterminierung denken.

dust258 5. Okt 2010 09:46

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Danke, das klingt plausibel, funktioniert aber leider nicht (gleiche Fehlermeldung aus der dll) ^^

Ich denke das mir einfach die nötigen debugging-Informationen fehlen (wie gesagt, das Record ist eine gekürzte Version). Ich werden mir wohl was anderes einfallen lassen.

Assarbad 14. Okt 2010 23:20

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Zitat:

Zitat von Zacherl (Beitrag 1053658)
Wenn ich mich nicht irre müsste unsigned char* das selbe wie ein PChar sein.

Nicht mehr ab Delphi 2009, als Unicode eingeführt wurde. Dann mindestens PAnsiChar oder gleich ^Byte.

An den Fragesteller kann man nur bemerken, daß er nicht einfach die wichtigsten Teile in seiner Frage weglassen sollte, wenn er eine Antwort erwartet. Ich habe mehrfach drübergelesen und noch immer nicht

Zitat:

Zitat von dust258 (Beitrag 1053654)
Code:
SIGN = (SIGN_TYPE) GetProcAddress(hMod, "SecSigner_Sign");


int signDocs(DOCUMENT documents[], int documentCount,
          BYTEARRAY cipherCerts[], int cipherCertCount,
          BYTEARRAY softKeyData[], int softKeyDataCount)
{
   int ret = (*SIGN)(documents, documentCount, cipherCerts, cipherCertCount, softKeyData, softKeyDataCount);
   

   return ret;
}

... den Funktionstyp SIGN_TYPE irgendwo deklariert gesehen. Und allem Anschein nach ist dies die Stelle wo es klemmt. Also? ;)

SirThornberry 15. Okt 2010 05:54

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Zitat:

Zitat von Zacherl (Beitrag 1053658)
Wenn ich mich nicht irre müsste unsigned char* das selbe wie ein PChar sein.

nicht ganz. "unsigned char*" ist ein "^Byte"
ein P(Ansi)Char wäre "char*"

phaeteon 10. Nov 2021 11:16

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Hallo dust,

gab es eine Lösung - sitze nun Jahre später an dem gleichen Problem,

secsigner_sign - stets mit Statuscode -3!

mfg
Uwe

Blup 11. Nov 2021 09:05

AW: Parameterübergabe an externe DLL (Pointer, Array, u.s.w.)
 
Sollte im Prinzip so funktionieren:
Delphi-Quellcode:
type
  PDocument = ^TDocument;
  TDocument = packed record
    Version: Integer;
    FileName: PAnsiChar;
    Data: Pointer;
    DataLen: Integer;
  end;

function Sign(Document: PDocument; DocumentCount: Integer;
              cipherCerts: Pointer; cipherCertCount: Integer;
              softKeyData: Pointer; softKeyDataCount: Integer): Integer;
Von den Arrays wird nur immer die Adresse des ersten Elements übergeben.

Zu TDocument:
- Für Data kann man direkt die Adresse und Größe des Puffers eines MemmoryStream verwenden.
- Filename muss irgendwo als AnsiString zwischengespeichert werden, solange TDocument in Verwendung ist (damit der Zeiger gültig bleibt).

Sollte es dann immer noch Fehler geben, vollständigen Quellcode der Umsetzung mit Deklarationen bitte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf