[英]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.