Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Paradoxes verhalten beim Aufruf einer C++ DLL aus Delphi (https://www.delphipraxis.net/155702-paradoxes-verhalten-beim-aufruf-einer-c-dll-aus-delphi.html)

dust258 4. Nov 2010 11:46

Paradoxes verhalten beim Aufruf einer C++ DLL aus Delphi
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Leute,
ich beschäftige mich im Moment mit der dll-Programmierung unter C++. Mir ist allerdings aufgefallen das von alle Integer-Werten, die ich von Delphi aus in meine DLL übergebe, immer 1 abgezogen wird...
Ich habe also die Funktion in einem Testprojekt nachgestellt, und auch hier tritt der "Fehler" auf. Kann mir das Jemand erklären?

Hier mein Delphi Testprojekt:
Delphi-Quellcode:
unit u_FormAufruf;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

  type
    TSecSigner_AssignDocuments   =
    function( inArrDocs : Array of PChar;
            inIDocCount : Integer)
          : Integer; cdecl;
type
  TFormMain = class(TForm)
    Button1: TButton;
    reDisplay: TRichEdit;
    edDllName: TEdit;
    edDllFunktion: TEdit;
    lbDllName: TLabel;
    lbDllFunktion: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    fLibHandle: THandle;
    SecSigner_AssignDocuments : TSecSigner_AssignDocuments;
    function loadSecSignerLibrary: Boolean;
  public
    { Public-Deklarationen }
  end;

var
  FormMain: TFormMain;

implementation

{$R *.dfm}

procedure TFormMain.Button1Click(Sender: TObject);
var
  lArrDocs : Array of PChar;
  lICount,
  lIResult,
  I: Integer;
begin

  SetLength(lArrDocs, 4);
  lArrDocs[0] := 'test1';
  lArrDocs[1] := 'test2';
  lArrDocs[2] := 'test3';
  lArrDocs[3] := 'test4';

  if loadSecSignerLibrary then
  try
    if Assigned(SecSigner_AssignDocuments) then
    begin
      lICount := Length(lArrDocs);
      for I := 0 to Length(lArrDocs) - 1 do
      begin
        reDisplay.Lines.Add('-'+lArrDocs[i]);
      end;
      reDisplay.Lines.Add('Übergabe Count: '+IntToStr(lICount));
      lIResult := SecSigner_AssignDocuments(lArrDocs, lICount); //Hier Hat lICount den Wert 4
      reDisplay.Lines.Add('Result: '+IntToStr(lIResult));
    end else
      reDisplay.Lines.Add('Funktion nicht gefunden');
  finally
    freeLibrary(fLibHandle);
  end;
end;

function TFormMain.loadSecSignerLibrary: Boolean;
begin
  Result := true;
  try
    fLibHandle := loadLibrary(PChar(edDllName.text));
    if fLibHandle <> 0 then
    begin
      @SecSigner_AssignDocuments := getProcAddress(fLibHandle, PChar(edDllFunktion.Text));
      reDisplay.Lines.Add('getProcAddress erfolgreich');
    end else
    begin
      Result := false;
      reDisplay.Lines.Add('DLL nicht gefunden');
    end;
  except
    Result := false;
  end;
end;

end.
und die C++ DLL:
Code:
#include "stdafx.h"
#include <windows.h>
#include "DllTest.h"
#include <TCHAR.H>
#include <stdio.h>

#pragma comment (lib, "user32.lib")



extern "C" __declspec(dllexport)int AssignDocuments(char* inArrFilenames[], int inIDocCount);
int AssignDocuments(char* inArrFilenames[], int inIDocCount)
{
   int i = inIDocCount;
   TCHAR str1[100];
   _stprintf(str1, _T("inIDocCount = %d"), inIDocCount);

   TCHAR str2[100];
   _stprintf(str2, _T("i in C++ = %d"), i); //Hier gibt die MessageBox 3 Aus

   MessageBox ( NULL, str1, str2, MB_OK);
   return i;
}
Das Projekt befindet sich außerdem im Anhang.

Assarbad 4. Nov 2010 11:55

AW: Paradoxes verhalten beim Aufruf einer C++ DLL aus Delphi
 
Erstmal:
Code:
int const i = inIDocCount; // konstant deklarieren
Guck mal ob das was ändert. Sollte zwar nicht, aber ist ohnehin die bessere Vorgehensweise.

Ansonsten sehe ich, daß die DLL eine .NET-Assembly ist. Hmm. Aber sollte nix ausmachen. Aber dennoch, warum? Der Code ist doch reines C++, warum als managed Kompilieren? Wo ist da der Vorteil für dich?

Und vor allem ist für mich nicht ersichtlich wo das passieren woll, was du sagst:

Code:
  .method assembly static modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) int32 AssignDocuments(modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsSignUnspecifiedByte) int8** inArrFilenames, int32 inIDocCount)
  {
    .maxstack 4
    .locals (valuetype <CppImplementationDetails>.$ArrayType$$$BY0GE@_W V0,
             valuetype <CppImplementationDetails>.$ArrayType$$$BY0GE@_W V1)
    ldloca.s 1
    ldsflda modopt([mscorlib]System.Runtime.CompilerServices.IsConst) valuetype <CppImplementationDetails>.$ArrayType$$$BY0BB@$$CB_W ??_C@_1CC@JEIJDBMP@?$AAi?$AAn?$AAI?$AAD?$AAo?$AAc?$AAC?$AAo?$AAu?$AAn?$AAt?$AA?5?$AA?$DN?$AA?5?$AA?$CF?$AAd?$AA?$AA@
    ldarg.1
    call modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) int32 _swprintf(char*, modopt([mscorlib]System.Runtime.CompilerServices.IsConst) char*, int32)
    pop
    ldloca.s 0
    ldsflda modopt([mscorlib]System.Runtime.CompilerServices.IsConst) valuetype <CppImplementationDetails>.$ArrayType$$$BY0O@$$CB_W ??_C@_1BM@LPOBPDGL@?$AAi?$AA?5?$AAi?$AAn?$AA?5?$AAC?$AA?$CL?$AA?$CL?$AA?5?$AA?$DN?$AA?5?$AA?$CF?$AAd?$AA?$AA@
    ldarg.1
    call modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) int32 _swprintf(char*, modopt([mscorlib]System.Runtime.CompilerServices.IsConst) char*, int32)
    pop
    ldc.i4.0
    ldloca.s 1
    ldloca.s 0
    ldc.i4.0
    call T0x6000055
    pop
    ldarg.1
    ret
  }

Dezipaitor 4. Nov 2010 12:19

AW: Paradoxes verhalten beim Aufruf einer C++ DLL aus Delphi
 
Delphi-Quellcode:
Array of PChar
ist nicht kompatibel mit
Code:
char* inArrFilenames[]
.
Benutze stattdessen

Delphi-Quellcode:
  type
    TSecSigner_AssignDocuments   =
    function( inArrDocs : PPChar;
            inIDocCount : Integer)
          : Integer; cdecl;
und

Delphi-Quellcode:
lIResult := SecSigner_AssignDocuments(@lArrDocs, lICount);

dust258 17. Nov 2010 07:38

AW: Paradoxes verhalten beim Aufruf einer C++ DLL aus Delphi
 
Hab mal Zeit gefunden das zu testen.

@Assarbad
Stimmt, in Zukunft werde ich sowas konstant deklarieren. Danke für den Tipp.
Ich habe nur die Logik aus der dll genommen um ein möglichst einfaches Beispiel zu liefern. In der "echten" Funktion benötige ich .Net Features.

@Dezipaitor
Das war es, jetzt funktioniert es ohne Probleme. D A N K E


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:10 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