从Delphi调用C#DLL,带有byte参数数组

时间:2017-07-15 15:16:29

标签: c# delphi

我为访问控制上的特定操作调用了一个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

修改代码以更清楚地解释我的情况。你能帮忙吗?

1 个答案:

答案 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', '', '', '');