Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   32/64bit DLL und Platform unterschiedliches Verhalten (https://www.delphipraxis.net/213804-32-64bit-dll-und-platform-unterschiedliches-verhalten.html)

taveuni 27. Sep 2023 15:10

32/64bit DLL und Platform unterschiedliches Verhalten
 
Sorry für den möglicherweise verwirrenden Titel und mein Unverständnis in diesem Fall.
Für ein Subsystem verwenden wir seit Jahren eine 32bit (C-) DLL API des Herstellers. Diese konsumieren wir mit einer Delphi 32bit Version.
Nun ist die 32bit API abgekündigt und wir migrieren auf eine Delphi 64bit Applikation und verwenden die 64bit API. Nun bin ich auf ein Problem im Callback gestossen.
Als Beispiel eine Methode und das Callback. Die C Header Datei sieht so aus:

Code:

/**
* @brief Structure holding basic input parameters
*/
typedef struct dlm_basicParametersStructure
{
   unsigned long ulFunctionID;                                    ///< Function ID
   int SessionHandle;                                       ///< Session ID
} dlm_basicParameters;



DLM_API int DLM_CALL_CONV dlm_getStreamingServerConfiguration(
   int SessionHandle,
   void (DLM_CALL_CONV *callback)(void *pParameters, void *pResult, void *pInput),
   void *pInput
);

/**
* Structure holding a callback result
*/
typedef struct XmlCallbackResult_
{
   int32_t iResult;                  ///< Result
   const char *xml;                  ///< Concomitant XML
} XmlCallbackResult;
Der *pResult Parameter enthält dann in diesem Fall den int32 und ein XML.

In Delphi ist das ganze so deklariert:

Delphi-Quellcode:
  Tdlm_getStreamingServerConfiguration = function(SessionHandle: Integer;
                                                   pParameters: pointer;
                                                   pInput: Pointer) : Integer; stdcall;

  TDlmXmlCallbackResult = packed record
    iResult : Int32;
    Xml : PAnsiChar;
  end;
  PDlmXmlCallbackResult = ^TDlmXmlCallbackResult;


  TDlmBasicCallbackData = packed record
    ulFunctionId : Cardinal;
    iSessionHandle : Integer;
  end;
  PDlmBasicCallbackData = ^TDlmBasicCallbackData;
Beim Empfang des Callbacks passiert folgendes:

Delphi-Quellcode:
procedure TDlmApiCallbackSingleton.ApiCallback(pParameters, pResult, pInput: pointer);
var
  p: PDlmBasicCallbackData;
  Res: Integer;
  XmlRes: PDlmXmlCallbackResult;
begin
    p:= pParameters;
    Res:= pInteger(pResult)^;
    TLogger.Log.Debug('Dlm callback event. FuncId: %d, Session: %d, ErrCode: %d',[p.ulFunctionId, p.iSessionHandle, Res],'DlmSdk');

    case p.ulFunctionId of
    res_getStreamingServerConfiguration:
    begin
      XmlRes:= PDlmXmlCallbackResult(pResult);
      var i:= XMLRes.iResult; // 32 und 64bit korrekter Wert
      if XMLRes.XML = '' then // Zugriffserverletzung 64bit
    end;
Nun habe ich eine TestApplikation mit einer 32bit und einer 64bit Plattform erstellt welche jeweils die korrekte API konsumiert.
Im 32bit Kompilat erhalte ich den XMLRes.XML eine PAnsichar mit einem XML. Im 64bit Kompilat erhalte ich eine Zugriffsverletzung. Was mache ich falsch?
Vermutlich ist TDlmXmlCallbackResult und/oder TDlmBasicCallbackData falsch deklariert? Und zufälligerweise hats bei 32bit geklappt?
Ich habe schon mit Ausrichtung der Recordfelder experimentiert. Leider ohne Erfolg. Kann mir jemand helfen?

himitsu 27. Sep 2023 16:04

AW: 32/64bit DLL und Platform unterschiedliches Verhalten
 
Sicher, dass der Record packed sein soll?

Ohne Packed liegt im TDlmXmlCallbackResult das XML unter 64 Bit bei Offset 8, aber mit packed bei Offset 4.

Delphi und C++ nutzen aktuell standardmäßig ein Allignment von 8.
https://docwiki.embarcadero.com/RADS...ields_(Delphi)



Falls du in die Assembler-Ansicht gucken solltest, dann nicht erschrecken, denn der Compiler ignoriert unter 64 Bit das stdcall und alle anderen CallingConventions, da es dort nur noch eine Convention gibt (und Diese sieht zufällig fast wie vom Pascal/Delphi aus ... da haben Intel, Microsoft und alle Anderen ganz bestimmt bei uns abgeguckt :stupid:)

taveuni 27. Sep 2023 16:09

AW: 32/64bit DLL und Platform unterschiedliches Verhalten
 
Zitat:

Zitat von himitsu (Beitrag 1527458)
Sicher, dass der Record packed sein soll?

Ohne Packed liegt im TDlmXmlCallbackResult das XML unter 64 Bit bei Offset 8, aber mit packed bei Offset 4.

Delphi und C++ nutzen aktuell standardmäßig ein Allignment von 8.



Falls du in die Assembler-Ansicht gucken solltest, dann nicht erschrecken, denn der Compiler ignoriert unter 64 Bit das stdcall und alle anderen CallingConventions, da es dort nur noch eine Convention gibt (und Diese sieht zufällig fast wie vom Pascal/Delphi aus ... da haben Intel, Microsoft und alle Anderen ganz bestimmt bei uns abgeguckt :stupid:)

Du bist mein HELD! Ich habe das packed entfernt und erhalte das korrekte Resultat.
Vielen herzlichen Dank!


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:42 Uhr.

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