首页 文章

C#Dllimport Delphi指针

提问于
浏览
1

我是编程新手,有人可以帮我调用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);
}

`

1 回答

  • 2

    这个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功能设计很差 . 如前所述,在这种情况下习惯使用以null结尾的字符串 . 这样做允许你让p / invoke marshaller处理锅炉板代码 . 您的错误代码也很差 . 如果用户传递的大小不足以存储字符串,则应让他们知道需要多少空间 .

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

    最后一条建议 . 您的函数返回指示是否成功的值 . 您的C#代码只是忽略那些返回值 . 作为一个广泛的规则,如果一个函数返回一个值,你应该注意它 . 特别是在执行互操作时,返回值表示成功或失败 .

相关问题