下面是一个调用dll并返回值的最小代码段。它工作正常。
dll(rtlsdr.dll)来自Software Defined Radio字段,控制一个小型USB加密狗。
代码工作正常,但只有我有虚拟变量' var junk:Integer'在函数getCenterFrequency中。如果我将其删除或发表评论,我会收到内存故障:
地址0012FEAE的访问冲突。读取地址00000000
如果我直接访问加密狗,而不是通过调用该函数,它可以正常工作。
如果我从Delphi UI或直接运行EXE,我会得到相同的结果。
我已经安装了EurekaLog,但它没有捕获异常。
什么可能导致这种奇怪的行为? Delphi XE2最新版本,Windows 7。
unit uTest;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
const
rtldll = 'rtlsdr.dll';
type
TfrmTest = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
function getCenterFrequency: longword;
public
{ Public declarations }
_dev: Pointer;
end;
var
frmTest: TfrmTest;
_dev: Pointer;
implementation
{$R *.dfm}
function rtlsdr_open(rtlsdr_dev_t: Pointer; index: UINT32): Integer; stdcall; external rtldll;
function rtlsdr_get_center_freq(rtlsdr_dev_t: Pointer): Integer; stdcall; external rtldll;
function TfrmTest.getCenterFrequency: longword;
//var
//junk: Integer;
begin
Result := rtlsdr_get_center_freq(_dev);
end;
procedure TfrmTest.FormCreate(Sender: TObject);
var
CF1, CF2: longword;
begin
_dev := 0;
if rtlsdr_open(@_dev, 0) <> 0 then
ShowMessage('error');
CF1 := rtlsdr_get_center_freq(_dev);
CF2 := getCenterFrequency;
end;
end.
答案 0 :(得分:3)
RTLSDR函数使用cdecl
调用约定,而不是stdcall
调用约定。另外,我建议您更改Pointer
指针以匹配DLL实际使用的rtlsdr_dev_t
类型。
type
rtlsdr_dev_t = record
end;
prtlsdr_dev_t = ^rtlsdr_dev_t;
function rtlsdr_open(out dev: prtlsdr_dev_t; index: UInt32): Integer; cdecl; external rtldll;
function rtlsdr_close(dev: prtlsdr_dev_t): Integer; cdecl; external rtldll;
function rtlsdr_get_center_freq(dev: prtlsdr_dev_t): UInt32; cdecl; external rtldll;
然后你可以这样做:
var
_dev: prtlsdr_dev_t = nil;
function TfrmTest.getCenterFrequency: Uint32;
begin
Result := rtlsdr_get_center_freq(_dev);
end;
procedure TfrmTest.FormCreate(Sender: TObject);
var
CF1, CF2: UInt32;
begin
_dev := nil;
if rtlsdr_open(_dev, 0) <> 0 then
begin
ShowMessage('error');
Exit;
end;
CF1 := rtlsdr_get_center_freq(_dev);
CF2 := getCenterFrequency;
rtlsdr_close(_dev);
_dev := nil;
end;
答案 1 :(得分:2)
据我所知,这个库导出了cdecl
个函数。您已导入stdcall
。仅这一点就足以导致您报告的行为。