Delphi 有人能帮我解决这个错误吗?我在尝试用dll打开端口时遇到了这个错误

Delphi 有人能帮我解决这个错误吗?我在尝试用dll打开端口时遇到了这个错误,delphi,dll,tcp,Delphi,Dll,Tcp,有人能帮我解决这个错误吗?我在尝试用dll打开端口时遇到了这个错误。当我呼叫SAAT_Open(myCharPtrOpen)时,我收到一个错误:“地址0003D078处的访问冲突”。不确定我是否在单元API上正确定义了句柄。变量幻影定义正确吗? 这是我的密码: procedure TForm5.Button1Click(Sender: TObject); var myString, myString2 : string; myCharPtrInit: PChar; myCh

有人能帮我解决这个错误吗?我在尝试用dll打开端口时遇到了这个错误。当我呼叫SAAT_Open(myCharPtrOpen)时,我收到一个错误:“地址0003D078处的访问冲突”。不确定我是否在单元API上正确定义了句柄。变量幻影定义正确吗? 这是我的密码:

procedure TForm5.Button1Click(Sender: TObject);
 var
   myString, myString2  : string;
   myCharPtrInit: PChar;
   myCharPtrOpen: PChar;
   i : Integer;
   Open, Init: Boolean;
 begin
  // Create a string of Char's
  myString  := '&hp';
  // Point to the first character in the string
  i := 1;
  myCharPtrInit := Addr(myString[i]);
  if SAAT_TCPInit(myCharPtrInit,'192.168.3.238',7086) = True then
  begin
    StatusBar1.Panels[0].Text := 'Initiated'; //ShowMessage('Initiated');
    myString2 := 'hp';
    myCharPtrOpen := Addr(myString2[i]);
    if SAAT_Open(myCharPtrOpen) = True then StatusBar1.Panels[1].Text := 'Opened';   
  end;
end;


unit UntRFIDAPI;

INTERFACE
uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Dialogs,
  StdCtrls, Forms, DBCtrls, DB, Grids, DBGrids,Mask, ExtCtrls,
  Buttons, WinTypes;

var
  A: String;

function SAAT_TCPInit(pHandle: Pointer; pHostName: String; nsocketPort: Integer):Boolean; stdcall;
function SAAT_Open(pHandle: Pointer):Boolean; stdcall;
function SAAT_Close(pHandle: Pointer):Boolean; stdcall;

implementation

function SAAT_TCPInit;  external 'RFIDAPI.dll';
function SAAT_Open;  external 'RFIDAPI.dll';
function SAAT_Close;  external 'RFIDAPI.dll';

end.
以下是API调用:

1.1初始化以太网端口(TCP)连接

//TCP parameters initialization 
//Functionality:import by parameter, initialize TCP to prepare for opening connection
//Parameters: 
//  pHandle for preserving the opening ports handl 
//  pHostName reader IP address, only effective under the ethernet communication 
//  nsocketPort network SOCKET port 
//Returned value:true: Operation Succeeded, false Operation Failed 

bool SAAT_TCPInit (void** pHandle,char *pHostName,int nsocketPort)
如果连接到读卡器的IP为192.168.0.238,端口为7086,则按如下方式调用:

HANDLE hp; 
if (!SAAT_TCPInit(&hp, ”192.168.0.238”, 7086)) 
{ 
    printf("reader initialization failed!\n"); 
    return false; 
}
此函数生成类型为
void*
的新句柄。在映射到
指针的Delphi中,一种非类型指针。因为C只支持按值传递,为了让函数将值传递给调用者,参数被声明为指向
void*
,即
void**

char*
是一个输入参数,指向以null结尾的8位字符数组的指针。映射到
PAnsiChar
。绝对不能使用
字符串
进行互操作。它是一个私有的Delphi类型,对于互操作来说根本无效

由于没有指定调用约定,我们假设它是
cdecl

因此,正确的翻译是:

function SAAT_TCPInit(out Handle: Pointer; HostName: PAnsiChar; 
  SocketPort: Integer): Boolean; cdecl; external 'RFIDAPI.dll';
我们已经将句柄类型,
void*
映射到
指针
。而
out
的使用引入了所需的额外间接级别

可以这样称呼:

var
  Handle: Pointer;
....
if SAAT_TCPInit(Handle, '192.168.3.238', 7086) then
  ....
function SAAT_Open(Handle: Pointer): Boolean; cdecl; external 'RFIDAPI.dll';
DLL中的函数实际上是
stdcall
,这似乎是合理的,即使您提供的C原型没有指定这一点。如果是这样的话,并且只有您能够解决这个问题,那么您可以相应地更改调用约定。事实上,Remy已经找到了头文件,并显示了函数是
stdcall

我们看不到另一个函数的C声明,但它们看起来非常简单。它们似乎都接受调用SAAT\u TCPInit
返回的句柄。因此,它们应该接受一个类型为
指针
、由值传递的参数。大概是这样的:

var
  Handle: Pointer;
....
if SAAT_TCPInit(Handle, '192.168.3.238', 7086) then
  ....
function SAAT_Open(Handle: Pointer): Boolean; cdecl; external 'RFIDAPI.dll';
同样,对于
SAAT_Close

为了清晰起见,为这个句柄定义一种新类型可能会更好。像这样:

type
  TSAATHandle = type Pointer;
或者如果您愿意:

type
  TSAATHandle = type NativeUInt;
很明显,您会使用这种类型,而不是
指针

此函数生成类型为
void*
的新句柄。在映射到
指针的Delphi中,一种非类型指针。因为C只支持按值传递,为了让函数将值传递给调用者,参数被声明为指向
void*
,即
void**

char*
是一个输入参数,指向以null结尾的8位字符数组的指针。映射到
PAnsiChar
。绝对不能使用
字符串
进行互操作。它是一个私有的Delphi类型,对于互操作来说根本无效

由于没有指定调用约定,我们假设它是
cdecl

因此,正确的翻译是:

function SAAT_TCPInit(out Handle: Pointer; HostName: PAnsiChar; 
  SocketPort: Integer): Boolean; cdecl; external 'RFIDAPI.dll';
我们已经将句柄类型,
void*
映射到
指针
。而
out
的使用引入了所需的额外间接级别

可以这样称呼:

var
  Handle: Pointer;
....
if SAAT_TCPInit(Handle, '192.168.3.238', 7086) then
  ....
function SAAT_Open(Handle: Pointer): Boolean; cdecl; external 'RFIDAPI.dll';
DLL中的函数实际上是
stdcall
,这似乎是合理的,即使您提供的C原型没有指定这一点。如果是这样的话,并且只有您能够解决这个问题,那么您可以相应地更改调用约定。事实上,Remy已经找到了头文件,并显示了函数是
stdcall

我们看不到另一个函数的C声明,但它们看起来非常简单。他们都似乎都接受调用
SAAT\u TCPInit
返回的句柄。因此,它们应该接受一个类型为
指针
、由值传递的参数。大概是这样的:

var
  Handle: Pointer;
....
if SAAT_TCPInit(Handle, '192.168.3.238', 7086) then
  ....
function SAAT_Open(Handle: Pointer): Boolean; cdecl; external 'RFIDAPI.dll';
对于
SAAT_Close
,情况也类似

为了清晰起见,最好为该手柄定义一种新类型。像这样:

type
  TSAATHandle = type Pointer;
或者如果您愿意:

type
  TSAATHandle = type NativeUInt;

很明显,您会使用这种类型,而不是
指针

您对C标题的翻译非常糟糕。我没有其他函数的原型,但是
SAAT\u TCPInit
应该声明为:

function SAAT_TCPInit(var pHandle: THandle; pHostName: PAnsiChar; nSocketPort: Integer): ByteBool;
    cdecl;
C对Delphi字符串一无所知,所以不要将C字符串翻译为Delphi的类型
string
,因为它与二进制文件不兼容
char*
应翻译为
PAnsiChar
void**pHandle
应翻译为
var pHandle:THandle
。调用约定可能是
cdecl

这假定使用正常校准约定。如果将其设置为生成
stdcall
,则必须声明它,而不是
cdecl

我想这是你的主要问题。请更正翻译,然后重试


有关翻译C标题的更多信息,请参阅我的文章(立即获取,因为网站可能会离线一段时间,我将切换提供商)。

您的C标题翻译几乎处于关闭状态。我没有其他函数的原型,但是
SAAT\u TCPInit
应该声明为:

function SAAT_TCPInit(var pHandle: THandle; pHostName: PAnsiChar; nSocketPort: Integer): ByteBool;
    cdecl;
C对Delphi字符串一无所知,所以不要将C字符串翻译为Delphi的类型
string
,因为它与二进制文件不兼容
char*
应翻译为
PAnsiChar
void**pHandle
应翻译为
var pHandle:THandle
。调用约定可能是
cdecl

这假定使用正常校准约定。如果设置为生成
stdcall
,则您必须声明它,而不是
cd