【发布时间】:2016-11-21 17:42:14
【问题描述】:
我正在尝试从 Delphi 调用 C++ 代码。我是初学者。我不断收到访问冲突错误,尽管它是间歇性的(但很常见)。
这仅在执行ConfigccDLL 或PriorTran 时发生。据我所知,这可能是调用约定不匹配,但我的印象是我在两个代码库中都使用了stdcall。我已经遍历了我使用 Dependency Walker 创建的 dll,并将函数显示为 _functionName。我不确定是否应该使用前导下划线来调用它们。
我想尽可能少地更改 Delphi 代码,因为最终将使用我无法更改的 dll 的代码(我想说我根本无法更改它,但我已经不得不更改 PAnsiChar 并添加 AnsiStrings 以使 Delphi 编译)。
德尔福代码:
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.
C++代码如下:
头文件:
#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 文件:
#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()
{
}
}
从依赖walker中看到的Dll
Dependency Walker 在打开 dll 时也会出现这些错误
【问题讨论】:
-
导出函数的名称是
_PriorTran@4,而不是您的 Delphi 代码所述的PriorTran。如果您想在您的 DLL 中“干净”导出名称,您需要使用 Module Definition File 构建您的 DLL -
请不要让这个问题成为一个移动的目标。
-
我没有尝试,但如果人们要提出更改建议,我将实施它们。
-
没有。那是不对的。你没有调用那个 dll,所以你对它做了什么并不重要。但不要破坏这个问题。
-
@DavidHeffernan 你是对的。不再违反访问权限。