簡體   English   中英

使用字節參數數組從Delphi調用C#DLL

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM