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