我为访问控制上的特定操作调用了一个dll“plcommpro.dll” 以下C#代码工作正常,并在缓冲区中正确检索数据
[DllImport("plcommpro.dll", EntryPoint = "GetDeviceData")]
public static extern int GetDeviceData(IntPtr h, ref byte buffer,
int buffersize, string tablename, string filename, string filter, string
options);
现在,我需要从Delphi编写相同的操作,所以我尝试了以下内容:
TGetDeviceData = Function(iDevID : NativeInt; buffer : Pbyte ; iSize :
Integer;
tablename, filename, strFilter, strOptions : PAnsiChar) : Int64;stdcall;
我按如下方式调用该函数:
var
myBuffer : TBytes;
iRetLog : Integer;
bufferSize : Integer;
sConnect : TConnect;
GetDeviceData : TGetDeviceData;
dllHandle : THandle;
iDevID : Integer;
begin
dllHandle := LoadLibrary('plcommpro.dll') ;
if dllHandle <> 0 then
begin
@sConnect := GetProcAddress(dllHandle, 'Connect');
if @sConnect <> Nil then
begin
strParams := PChar('protocol=TCP,ipaddress=' + grd_Machines.Cells[cl_Machine_IP, iLoop] + ',port=4370,timeout=2000,passwd=');
iDevID := sConnect(strParams);
strTableName := PAnsiChar(AnsiString(('user')));
strDatas := PAnsiChar(AnsiString(''));
strFileName := PAnsiChar(AnsiString(''));
strFilter := PAnsiChar(AnsiString(''));
strOptions := PAnsiChar(AnsiString(''));
@GetDeviceData := GetProcAddress(dllHandle, 'GetDeviceData');
if @GetDeviceData <> Nil then
begin
try
buffersize := 1024*1024;
//bufferSize := MaxInt - 1;
SetLength(myBuffer, 1024*1024);
mem_AttLogs.Lines.Add('buffer Size : ' + IntToStr(buffersize) );
iRetLogs := GetDeviceData(iDevID, PByte(myBuffer[0]), buffersize, strTableName, strFileName, strFilter, strOptions);
if iRetLogs > 0 then
begin
....
//Here: I need to read the returned values from the function; but it always fails
end
修改代码以更清楚地解释我的情况。你能帮忙吗?
答案 0 :(得分:0)
你给出的C#声明显然有缺陷:ref byte buffer
毫无意义。缓冲区不是一个字节。它可能应该是[out] byte[] buffer
(感谢David Heffernan)。两者都转换了底层指针,但在C#端完成的转换是不同的。
由于这似乎是用于与普通Windows DLL接口的互操作代码,我可以看到原始内容必须是什么:指向字节的指针,最好在Delphi中翻译为PByte
(但没有{{ 1}},这会引入一个间接层次太多)。
所以现在应该是这样的:
var
现在你终于更新了你的代码,你得到的错误非常明显:
var
GetDeviceData: function(h: THandle; buffer: PByte; buffersize: Integer;
tablename, filename, filter, options: PAnsiChar): Integer stdcall;
那是错的。您正在向指针投射iRetLog := GetDeviceData(iDevID, PByte(myBuffer[0]), buffersize,
strTableName, strFileName, strFilter, strOptions);
(即AnsiChar
)。你需要一个指向myBuffer[0]
的第一个元素的指针,所以:
myBuffer
FWIW,因为你似乎在使用常量字符串,你可以这样做:
iRetLog := GetDeviceData(iDevID, @myBuffer[0], buffersize,
strTableName, strFileName, strFilter, strOptions); // Note the @
为了使这更容易维护,如果你已经有一个具有这个数字的变量(并且必须是完全相同的大小),不要使用文字数字,所以这样做:
iRetLog := GetDeviceData(iDevID, @myBuffer[0], buffersize, 'user', '', '', '');