简体   繁体   English

C#Dllimport Delphi指针

[英]C# Dllimport Delphi Pointer

I'm new in programming, Can someone help me call a pointer function from a delphi dll into Visual C# function. 我是编程新手,有人可以帮我从delphi dll调用指针函数到Visual C#函数。

Here is the Delphi Function stored into the DLL. 这是存储在DLL中的Delphi函数。 // Delphi Code Stored in the DLL // 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 ` //Import a Function Pointer // 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);
}

` `

This Delphi function is kind of messy. 这种Delphi函数有点混乱。 Its job is to copy a string into a buffer supplied by the caller. 它的工作是将字符串复制到调用方提供的缓冲区中。 Normally that is done using null-terminated strings but the Delphi code does not do so. 通常,这是使用以null终止的字符串完成的,但是Delphi代码不会这样做。

Assuming that the Delphi code cannot be modified, here's how to call it from C#. 假定不能修改Delphi代码,这是从C#调用它的方法。 Note that you don't need unsafe code here and I recommend that you stop using unsafe code. 请注意,您在这里不需要不安全的代码,我建议您停止使用不安全的代码。

First of all the p/invoke declaration: 首先,p / invoke声明:

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

The Size parameter has type Integer in Delphi. Size参数在Delphi中具有Integer类型。 That's a 32 bit integer in C#. 这是C#中的32位整数。 So use int , just as you did for the return value. 因此,请像使用返回值一样使用int Don't use IntPtr which is an integer whose size equals that of a pointer. 不要使用IntPtr ,它是一个整数,其大小等于指针的大小。 That is incorrect in a 64 bit process. 这在64位进程中是不正确的。 The Msg parameter should be allocated as a byte array since you are not adding a null-terminator. Msg参数应分配为字节数组,因为您没有添加空终止符。 And that in turn means there is no need to specify CharSet . 这又意味着无需指定CharSet

Now the call: 现在调用:

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

Your Delphi function is poorly designed though. 但是,您的Delphi函数设计不良。 As mentioned already, it is customary to use null-terminated strings in this scenario. 如前所述,在这种情况下,习惯上使用以空值结尾的字符串。 Doing so allows you to let the p/invoke marshaller deal with the boiler plate code. 这样做可以让p / invoke marshaller处理样板代码。 Your error codes are poor also. 您的错误代码也很差。 If the user passes a size that is insufficient to store the string, you should let them know how much space is required. 如果用户传递的大小不足以存储字符串,则应让他们知道需要多少空间。

The implementation of the Delphi function is also sub-optimal. Delphi函数的实现也不理想。 Rather than copying byte-by-byte, you should copy the entire buffer in one shot. 而不是逐字节复制,您应该一次性复制整个缓冲区。

One final piece of advice. 最后一条建议。 Your function returns values indicating whether or not it succeeded. 您的函数将返回指示其是否成功的值。 Your C# code simply ignores those return values. 您的C#代码仅忽略这些返回值。 As a broad rule, if a function returns a value, you ought to be heeding it. 一般来说,如果函数返回一个值,则应注意它。 Especially when you are performing interop, and the return value indicates success or failure. 特别是在执行互操作时,返回值指示成功或失败。

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

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