Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用字节参数数组从Delphi调用C#DLL_C#_Delphi - Fatal编程技术网

使用字节参数数组从Delphi调用C#DLL

使用字节参数数组从Delphi调用C#DLL,c#,delphi,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

我将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
var
myBuffer:TBytes;
iRetLog:整数;
缓冲区大小:整数;
sConnect:t连接;
GetDeviceData:TGetDeviceData;
德尔汉德尔:坦德尔;
iDevID:整数;
开始
dllHandle:=LoadLibrary('plcommpro.dll');
如果dllHandle为0,则
开始
@sConnect:=GetProcAddress(dllHandle,'Connect');
如果@sConnect Nil,则
开始
strParams:=PChar('protocol=TCP,ipaddress='+grd_Machines.Cells[cl_Machine_IP,iLoop]+',port=4370,timeout=2000,passwd=');
iDevID:=连接(strParams);
strTableName:=PAnsiChar(AnsiString(('user'));
标准数据:=PAnsiChar(AnsiString(“”));
strFileName:=PAnsiChar(AnsiString(“”));
strFilter:=PAnsiChar(AnsiString(“”));
选择:=PAnsiChar(AnsiString(“”));
@GetDeviceData:=GetProcAddress(dllHandle,'GetDeviceData');
如果@GetDeviceData为零,则
开始
尝试
缓冲区大小:=1024*1024;
//bufferSize:=MaxInt-1;
设置长度(myBuffer,1024*1024);
mem_AttLogs.Lines.Add('buffer Size:'+IntToStr(buffersize));
iRetLogs:=GetDeviceData(iDevID,PByte(myBuffer[0]),buffersize,strTableName,strFileName,strFilter,strOptions);
如果iRetLogs>0,则
开始
....
//这里:我需要读取函数返回的值;但它总是失败
结束
代码被修改以更清楚地解释我的情况。你能帮忙吗?

你给出的C#声明显然有缺陷:
ref byte buffer
毫无意义。缓冲区不是一个字节。它可能类似于
[out]byte[]buffer
(感谢David Heffernan)。两者都转换一个底层指针,但在C#端完成的转换是不同的

由于这似乎是一个与普通Windows DLL接口的互操作代码,我可以看到原始代码是什么:一个指向字节的指针,在Delphi中最好翻译为
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
的第一个元素的指针,因此:

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);

var byte:PByte
错误(一级间接寻址太多)。首先,
Byte
是一种现有类型,虽然这可能是合法的,但我认为您应该将其命名为
buffer
之类的C#assembly。但更重要的是,您应该去掉
var
。所以,让它成为:
缓冲区:PByte
。FWIW,
ansisting
也错了。让它成为
PAnsiChar
。您能告诉我们如何访问您的字节吗?这是一个指向字节的指针,它通常引用字节数组,但您似乎引用的是单个字节。向我们展示用于尝试获取“byte”的代码将有所帮助。还要注意,在Delphi中,byte是一种数据类型,所以不同的名称可能会有所帮助。FWIW,对吗?这看起来好像是从非.NET DLL导入C#,因此使用了
DllImport
属性。如果是这种情况,您应该直接使用
plcommpro.dll
。也许它甚至有一个C头。是的,我正在直接使用“plcommpro.dll”。问题是,我无法从我的Delphi应用程序中获取数据,但我可以从C#App中获取数据。你有用于DLL的C头吗?如果是,则显示同一函数的C声明。而
PByte
实际上不应该是
var
参数。也不应将字符串转换为
AnsiString
(一种特定于Delphi的类型,在C或C#中不存在)。它应该是
PAnsiChar
,这是C语言中
char*
的翻译。NET编组代码将
char*
转换为C字符串,但在Delphi中不起作用。看一看关于使用DLLs.FWIW的内容,从我在网上找到的信息来看,
GetDeviceData
返回的是一个
整数,而不是
Int64
。最好将第一个参数声明为
THandle
。我假设这不是您真正的代码。您可以声明
iRetLog
,但稍后将使用
iRetLogs
。不要那样做。这会使您的代码难以理解,并引入不必要的错误。下次发布问题时,请提供更多、格式更好的代码。如果可能的话,还有真正的代码,或者。如果您从一开始就这样做了,您会更早得到答案。
ref byte buffer
只能映射到
var buffer:byte
,这显然毫无意义。但提问者接受了与c不匹配的答案。整个事情对于这个网站来说是一团糟,完全不合适。@大卫:是的,
ref byte buffer
只映射到
var buffer:byte
。在C#端,这只是一个糟糕的翻译(在现实生活中,指针被传递也是有效的,但无法使用)。我看过其他的翻译,一个字节的缓冲区是毫无意义的,我打赌
buffer:PByte
可以工作。