2016-11-21 3 views
2

Ich versuche, C++ - Code von Delphi aufrufen. Ich bin ein Anfänger. Ich erhalte immer noch einen Zugriffsverletzungsfehler, obwohl dieser intermittierend ist (aber sehr häufig).Richtig C++ - Funktionen in DLL aus Delphi "Zugriffsverletzung" aufrufen

Access violation

Dies geschieht nur, wenn ConfigccDLL oder PriorTran Von der Ausführung, was ich gelesen habe, es könnte eine Aufrufkonvention Mismatch sein, aber ich habe den Eindruck, ich stdcall in beiden Codebases verwenden. Ich habe die DLL, die ich mit Dependency Walker erstellt und die Funktionen als _functionName zeigt, ausgeführt. Ich bin mir nicht sicher, ob ich sie mit dem führenden Unterstrich anrufen sollte.

Ich möchte den Delphi-Code so wenig wie möglich ändern, weil der Code, der am Ende die DLL verwenden wird, ich nicht ändern kann (ich wollte sagen, ich kann es überhaupt nicht ändern, aber ich hatte bereits um den PAnsiChar zu ändern und AnsiStrings hinzuzufügen, damit Delphi kompiliert wird.

Delphi-Code:

unit dllTest; 

interface 

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

procedure CloseDLL; stdcall; external 'cccontrol.dll'; 
procedure ConfigccDLL(Variables: PAnsiChar); stdcall; external 'cccontrol.dll'; 
procedure PrepareDLL; stdcall; external 'cccontrol.dll'; 
procedure PriorTran(Variables: PAnsiChar); stdcall; external 'cccontrol.dll'; 


type 
    TdllTestForm = class(TForm) 
    PrepareBtn: TBitBtn; 
    Label1: TLabel; 
    ConfigccDLLbtn: TBitBtn; 
    TranTypeEntry: TEdit; 
    TranAmountEntry: TEdit; 
    Label2: TLabel; 
    PriorTranBtn: TBitBtn; 
    TranIDEntry: TEdit; 
    Label3: TLabel; 
    CloseDLLBtn: TBitBtn; 
    Label4: TLabel; 
    Memo1: TMemo; 
    BitBtn1: TBitBtn; 
    procedure CloseDLLBtnClick(Sender: TObject); 
    procedure PriorTranBtnClick(Sender: TObject); 
    procedure ConfigccDLLbtnClick(Sender: TObject); 
    procedure PrepareBtnClick(Sender: TObject); 

    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    dllTestForm: TdllTestForm; 

implementation 

{$R *.dfm} 

procedure TdllTestForm.PrepareBtnClick(Sender: TObject); 
var 
    AppHandle: HWND; 
begin 
    AppHandle := Application.Handle; 
    PrepareDLL; 
end; 

procedure TdllTestForm.ConfigccDLLbtnClick(Sender: TObject); 
var 
    Variables: AnsiString; 
    TransID, TransType, TranAmt: string; 
begin 
    TransType := TranTypeEntry.Text; 
    TranAmt := TranAmountEntry.Text; 
    Variables := TransType + '^' + TranAmt + '^'; 
    ConfigccDLL(PAnsiChar(Variables)); 
end; 

procedure TdllTestForm.PriorTranBtnClick(Sender: TObject); 
var 
    Variables: AnsiString; 
    TransID, TransType, TranAmt: string; 
begin 
    TransID := TranIDEntry.Text; 
    Variables := TransID; 
    PriorTran(PAnsiChar(Variables)); 
end; 

procedure TdllTestForm.CloseDLLBtnClick(Sender: TObject); 
begin 
    CloseDLL; 
end; 

end. 

Der C++ Code ist wie folgt:

Headerdatei:

#pragma once 

#ifndef ccControl 
#define ccControl 
#include <iostream> 

#if defined DLL_EXPORT 
#define DECLDIR __declspec(dllexport) 
#else 
#define DECLDIR __declspec(dllimport) 
#endif 

extern "C" { 
    DECLDIR void __stdcall PrepareDLL(); 
    DECLDIR void __stdcall ConfigccDLL(char* pcharVar); 
    DECLDIR void __stdcall PriorTran(char* pcharVar); 
    DECLDIR void __stdcall CloseDLL(); 
} 

#endif 

Cpp-Datei:

#include "stdafx.h" 

#include <iostream> 
#include <windows.h> 
#include <Winuser.h> 
#include <stdexcept> 

#define DLL_EXPORT 

#include "ccControl.h" 

#pragma warning(disable : 4996) 

using namespace std; 

extern "C" { 

    DECLDIR void __stdcall PrepareDLL() 
    { 

    } 

    DECLDIR void __stdcall ConfigccDLL(char* pcharVar) 
    { 

    } 

    DECLDIR void __stdcall PriorTran(char* pcharVar) 
    { 

    } 

    DECLDIR void __stdcall CloseDLL() 
    { 

    } 
} 

Dll wie aus der Abhängigkeit gesehen Gehhilfe

enter image description here

Dependency Walker gibt auch diese Fehler, wenn die DLL öffnen

enter image description here

+0

Der Name der exportierten Funktion ist '_PriorTran @ 4', nicht' PriorTran', wie Ihr Delphi-Code angibt. Wenn Sie exportierte Namen in Ihrer DLL "säubern" möchten, müssen Sie Ihre DLL mithilfe einer [Moduldefinitionsdatei] erstellen (http://stackoverflow.com/questions/31282683/dll-call-with-stdcall-getprocaddress-in- vs2013/31283377 # 31283377) – PaulMcKenzie

+0

Bitte machen Sie diese Frage nicht zu einem beweglichen Ziel. –

+0

Ich versuche es nicht, aber wenn die Leute Änderungen vorschlagen, werde ich sie implementieren. –

Antwort

1

Ich denke, es ist klar, dass Sie nicht die DLL aufrufen, die Sie denken, dass Sie anrufen. Wenn Sie dann wären, würde Ihr Programm nicht starten, weil die exportierten Funktionsnamen nicht übereinstimmen. Die DLL, die Sie in Dependency Walker anzeigen, hat Namen eingerichtet. Sie verwenden die dekorierten Namen in Ihrem Delphi-Code nicht. Ihr Programm wird ausgeführt. Ergo, Sie verlinken zu einer anderen DLL. Warum Sie eine Zugriffsverletzung erhalten, können wir sicherlich nicht sagen, weil wir überhaupt nichts über diese DLL wissen.

Sobald Sie es so sortiert, dass Sie die richtige DLL aufrufen (platzieren Sie die DLL im selben Verzeichnis wie Ihre ausführbare Datei), können wir den Code in der Frage betrachten. Das Interop dort ist in Ordnung, und in jedem Fall tun Ihre DLL-Funktionen nichts. Aber der Delphi-Code ist nicht gut. Betrachten Sie diesen Code:

Hier reservieren Sie ein Array der Länge 50, und kopieren Sie in eine Zeichenfolge der Länge wer weiß was. Wenn die Quellzeichenfolge zu lang ist, überschreiben Sie den Puffer.

Wenn Sie die dynamische Zuordnung verwenden müssen, müssen Sie Maßnahmen ergreifen, um sicherzustellen, dass die Puffer ausreichend lang sind. Außerdem müssen Sie die Zuordnung aufheben. Ihr Code ist derzeit wie ein Sieb undicht.

Aber manuelle dynamische Zuordnung ist fehleranfällig und mühsam. Begnügen Sie sich nicht mit einem Leben der Langeweile. Lassen Sie den Compiler die Arbeit für Sie erledigen. Erstellen Sie den Text in einer Variablen vom Typ AnsiString. Wenn Sie das an Ihren C++ - Code übergeben müssen, verwenden Sie eine PAnsiChar(...) Umwandlung.

var 
    Variables: AnsiString; 
.... 
Variables := TransType + '^' + TranAmt + '^'; 
ConfigccDLL(PAnsiChar(Variables)); 
+0

Ich bekomme immer noch Zugriffsverletzung Fehler bei der Verwendung von AnsiStrings. Sowie wenn ich 'CloseDLL' triggere (obwohl selten), obwohl es nur die externe Funktion aufruft. Wie für Delphi-Importcodes, die diese Namen nicht verwenden, bin ich nicht sicher, was Sie sagen. stdcall ist genau dort und die Angabe des dekorierten Namens löst einen ProcedureEntryPoint not found error aus. –

+0

Siehe meine aktualisierte Antwort. Offensichtlich rufen Sie nicht wirklich die DLL auf, die Sie kompiliert haben, und wer exportierte Namen sind dekoriert. –

+0

Benutzte Process Explorer, um herauszufinden, welche DLL die App anruft, stellt sich heraus, dass es auf einem Netzlaufwerk war (ich dachte, ich hätte alle Suchpfade in der IDE gelöscht, ich weiß nicht, wie es überhaupt funktioniert). Die DLL wurde mit vollständigen Dateipfad- und Zugriffsverletzungen nicht mehr angegeben. –

Verwandte Themen