[英]Calling a C# DLL from Delphi, with array of byte parameter
我為訪問控制上的特定操作調用一個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
修改代碼以更清楚地說明我的情況。 你能幫我嗎?
您提供的C#聲明顯然存在缺陷: ref byte buffer
毫無意義。 緩沖區不是一個字節。 它可能應該是[out] byte[] buffer
(感謝David Heffernan)。 兩者都轉換了基礎指針,但是在C#端完成的轉換是不同的。
由於這似乎是與普通Windows DLL進行交互的互操作代碼,因此我可以看到原始代碼必須是:指向字節的指針,最好在Delphi PByte
其翻譯為PByte
(但不要使用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[0]
轉換為指針。 您需要一個指向myBuffer
的第一個元素的myBuffer
,因此:
iRetLog := GetDeviceData(iDevID, @myBuffer[0], buffersize,
strTableName, strFileName, strFilter, strOptions); // Note the @
FWIW,因為您似乎正在使用常量字符串,所以可以執行以下操作:
iRetLog := GetDeviceData(iDevID, @myBuffer[0], buffersize, 'user', '', '', '');
為了使它更易於維護,如果您已經有一個具有該數字的變量(並且無論如何大小都必須完全相同),請不要使用立即數,因此,請執行以下操作:
buffersize := 1024*1024;
SetLength(myBuffer, buffersize);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.