繁体   English   中英

C#Dllimport Delphi指针

[英]C# Dllimport Delphi Pointer

我是编程新手,有人可以帮我从delphi dll调用指针函数到Visual C#函数。

这是存储在DLL中的Delphi函数。 // Delphi代码存储在DLL中

function DeviceName(Size : Integer; Msg : Pointer) : Integer stdcall;
var
  i: Integer;
  TempByte : PByte;
  TempName : string;
begin
  if DLLClass.DevList.HidDevices.Count > 0 then
  begin
    TempName := (DLLClass.DevList.HidDevices.Name[DLLClass.HIDTool.CurrentDeviceIndex]);
    if Length(TempName) <= Size then
    begin
      try
        TempByte := Msg;
        for i := 0 to Length(TempName) - 1 do
        begin
          TempByte^ := Ord(TempName[i+1]);
          Inc(TempByte)
        end;
        Result := Length(TempName);
      except
        Result := -2;
      end;
    end
    else
    begin
      Result := -3;
    end;
  end
  else
  begin
    Result := -1;
  end;
end;

// C#Code`//导入函数指针

[DllImport("HID_DLL.dll", CallingConvention= CallingConvention.StdCall,  CharSet = CharSet.Ansi)]
public unsafe static extern int DeviceName(IntPtr Size, [MarshalAs(UnmanagedType.LPStr)] string Msg);



unsafe static void Main()
{
byte[] buffer = new byte[32768];

       DeviceName(255, &**buffer);

            Console.WriteLine("%s\n" + buffer);
}

`

这种Delphi函数有点混乱。 它的工作是将字符串复制到调用方提供的缓冲区中。 通常,这是使用以null终止的字符串完成的,但是Delphi代码不会这样做。

假定不能修改Delphi代码,这是从C#调用它的方法。 请注意,您在这里不需要不安全的代码,我建议您停止使用不安全的代码。

首先,p / invoke声明:

[DllImport("Azoteq_HID_DLL.dll", CallingConvention= CallingConvention.StdCall]
public static extern int DeviceName(int Size, byte[] Msg);

Size参数在Delphi中具有Integer类型。 这是C#中的32位整数。 因此,请像使用返回值一样使用int 不要使用IntPtr ,它是一个整数,其大小等于指针的大小。 这在64位进程中是不正确的。 Msg参数应分配为字节数组,因为您没有添加空终止符。 这又意味着无需指定CharSet

现在调用:

byte[] Msg = new byte[256];
int retval = DeviceName(Msg.Length, Msg);
if (retval < 0)
{
    // handle error
}
else
{
    string name = Encoding.Default.GetString(Msg, 0, retval);
}

但是,您的Delphi函数设计不良。 如前所述,在这种情况下,习惯上使用以空值结尾的字符串。 这样做可以让p / invoke marshaller处理样板代码。 您的错误代码也很差。 如果用户传递的大小不足以存储字符串,则应让他们知道需要多少空间。

Delphi函数的实现也不理想。 而不是逐字节复制,您应该一次性复制整个缓冲区。

最后一条建议。 您的函数将返回指示其是否成功的值。 您的C#代码仅忽略这些返回值。 一般来说,如果函数返回一个值,则应注意它。 特别是在执行互操作时,返回值指示成功或失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM