2017-05-20 1 views
1

Ich habe eine C++ function:C++ Funktion Delphi XE7

long CSP2_API csp2GetPacket(char szData[], long nBcrNr, long nMaxDataSz) 

Parameter sind:

szData: buffer where the barcode data is stored in 
nBcrNr: the desired barcode’s index (which starts from 0L) 
nMaxDataSz: the maximum size of the szData buffer 

Mein Weg des Umgangs mit dieser ist:

type 
TBarcode  = Array[0..99] of AnsiChar; 


function csp2GetPacket(szBarData : TBarCode; 
         nBarcodeNumber: LongInt; 
         nMaxLength: LongInt): LongInt cdecl {$IFDEF WIN32}stdcall {$ENDIF}; external 'CSP2.DLL'; 

und Verwendung genannt. ..

procedure TForm1.Button1Click(Sender: TObject); 
var 
BarCode : TBarcode; 
begin 

    BarCode := #0; 
    csp2GetPacket(BarCode,0,SizeOf(BarCode)); 

end; 

Die C++ - Dokumentation bestätigt, dass der Standard ASCII Text für die Barcodes verwendet wird.

Gibt es einen besseren (korrekteren) Weg, das C++ function aufzurufen? oder ist das akzeptabel?

+0

@RawN 'AnsiChar' ist immer 1 Byte. Sie denken an Delphi 'Char', das 2 Bytes in D2009 + ist. 'char' in C++ ist immer 1 Byte, also ist' AnsiChar' in Delphi korrekt, * besonders * in D2009 +. –

+0

C++ normalerweise Mangelnamen. Was interessant zu wissen ist, ob dies als "extern" C "erklärt wird oder nicht.Wenn nicht, müssen Sie den richtigen Namen herausfinden. –

+0

@RudyVelthuis CSP2 API ist in C tatsächlich mit Aufrufkonventionen stdcall, nicht C++. Die Namen in der Importbibliothek werden dementsprechend gemangelt (z.B. '_csp2GetPacket @ 12'). Namen in der DLL, die die API bereitstellen, werden nicht gemangelt ('csp2GetPacket') –

Antwort

0

:

long CSP2_API csp2GetPacket(char szData[], long nBcrNr, long nMaxDataSz) 

wird wie folgt übersetzt:

function csp2GetPacket(szData: PAnsiChar; nBcrNr, nMaxDataSz: Longint): Longint; <calling-convention>; 

Ihre Übersetzung ist nicht korrekt. In C kann man ein Array zu einem Zeiger degradieren, aber in Delphi würde man wirklich das gesamte Array pro Wert übergeben, so dass die Übersetzung nicht binärkompatibel mit dem Original ist.

Ich nehme an, Sie haben die Aufrufkonvention richtig. Wenn nicht, entfernen Sie einfach die stdcall.

Ich würde einfach ein AnsiString als Parameter verwenden, zu einem PAnsiChar werfen, mehr oder weniger wie:

var 
    BarCode: AnsiString; 
    L: Longint; 
begin 
    SetLength(L, 100); 
    L := csp2GetPacket(PAnsiChar(BarCode), 0, Length(BarCode)); 
    // If csp2GetPacket returns the length, then: 
    SetLength(BarCode, L); 
    // Otherwise, this will work too: 
    BarCode := PAnsiChar(BarCode); // Copies up to and including terminating #0 

Ich weiß nicht, die Grenzen für die Länge des Puffers, so nahm ich die gleiche Länge als dein Code.

Weitere Informationen in meinem Artikel zum Thema Konversionen: Pitfalls of converting.

1

Wenn Sie die Barcode-Daten wissen nie 100 Bytes überschreiten, dann ist Ihr Ansatz ist in Ordnung, wenn Ihre Funktionsdeklaration wie dies stattdessen mehr sein soll:

type 
    TBarcode = Array[0..99] of AnsiChar; 

function csp2GetPacket(szBarData: TBarCode; nBarcodeNumber: LongInt; nMaxLength: LongInt): LongInt; cdecl; external 'CSP2.DLL'; 

Oder, wenn die Funktion wirklich stdcall nicht verwendet auf Windows statt cdecl:

function csp2GetPacket(szBarData: TBarCode; nBarcodeNumber: LongInt; nMaxLength: LongInt): LongInt; stdcall; external 'CSP2.DLL'; 

so oder so, eine korrekte Übersetzung der Funktion wäre, die szBarData Parameter als PAnsiChar stattdessen zu deklarieren:

Sie können weiterhin eine feste Array-Variable an einen PAnsiChar-Parameter übergeben. Diese

+0

Ist die erste Deklaration korrekt? Übergibt es wirklich einen Zeiger? Es muss irgendwann eine Kopie machen. Ich hätte erwartet, dass sich das Array auf dem Stapel bewegen würde. –

Verwandte Themen