从 C# 到 Delphi 的翻译
Translation from C# to Delphi
我需要帮助将部分 C# 代码翻译成 Delphi。
如果有任何帮助或建议,我将不胜感激。
unsafe {
fixed (byte* bpt = &buff[140]) {
byte b1 = bpt[0];
byte b2 = bpt[1];
byte b3 = bpt[2];
byte b4 = bpt[3];
}
}
我尝试了几种方法,用 4 字节变量定义记录,定义 tbytearray,但似乎都不对。
对此有什么想法吗?
谢谢。
更新
看来我的问题没有定义好,因为这是我的第一个问题,这里是C#上的完整函数。
private void ProcessCommAlarm_V40(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
{
MyDebugInfo AlarmInfo = new MyDebugInfo(DebugInfo);
byte[] buff = new byte[dwBufLen];
System.Runtime.InteropServices.Marshal.Copy(pAlarmInfo, buff, 0, (int)dwBufLen);
string sBuff = "";
if (dwBufLen - 140 > 0 && (dwBufLen - 140) % 4 == 0)
{
int msgType = BitConverter.ToInt32(buff, 0);
string sMsgType = "";
bool bAcceptedMsg = false;
int nTargetType = 0;
switch (msgType)
{
case 2:
sMsgType = "Video Loss"; bAcceptedMsg = true; nTargetType = 1; break;
case 3:
sMsgType = "Motion"; nTargetType = 1; break;
}
if (bAcceptedMsg)
{
int nTotalElements = BitConverter.ToInt32(buff, 12);
if ((nTargetType == 1 && nTotalElements <= CHCNetSDK.MAX_CHANNUM_V30) || (nTargetType == 2 && nTotalElements <= CHCNetSDK.MAX_DISKNUM_V30))
{
int len = nTotalElements * 4;
byte[] channels = new byte[len];
unsafe
{
fixed (byte* bpt = &buff[140])
{
byte b1 = bpt[0];
byte b2 = bpt[1];
byte b3 = bpt[2];
byte b4 = bpt[3];
IntPtr dwDataAddress = new IntPtr(b1 + b2 * (1 << 8) + b3 * (1 << 16) + b4 * (1 << 24));
System.Runtime.InteropServices.Marshal.Copy(dwDataAddress, channels, 0, len);
}
}
for (int i = 0; i <= len - 4; i += 4)
{
sBuff += string.Format("Channel No: {0}", BitConverter.ToInt32(channels, i));
sBuff += Environment.NewLine;
}
}
}
}
}
现在,这就是我到目前为止所做的,其中包括给我的 @remy-lebeau 所做的更改。
procedure ProcessCommAlarm_V40(pAlarmer: LPNET_DVR_ALARMER; pAlarmInfo: PChar; dwBufLen: DWORD; dwUser: DWORD);
var
buff: array of byte;
msgType: Integer;
sMsgType: String;
bAcceptedMsg: Boolean;
nTargetType: Integer;
sBuff: String;
nTotalElements: Integer;
channels: array of byte;
len: Integer;
b1,b2,b3,b4:byte;
bpt: pbyte;
dwDataAddress: IntPtr;
I: Integer;
begin
sBuff := '';
SetLength(buff, dwBufLen);
CopyMemory(buff, pAlarmInfo, dwBufLen);
if (dwBufLen - 140 > 0) and ((dwBufLen - 140) mod 4 = 0) then begin
msgType := Integer(buff[0]);
sMsgType := '';
bAcceptedMsg := false;
nTargetType := 0;
case (msgType) of
2:
begin
sMsgType := 'Video loss';
bAcceptedMsg := true;
nTargetType := 1;
end;
end;
if (bAcceptedMsg) then
begin
nTotalElements := buff[12];
if ((nTargetType = 1) and (nTotalElements <= MAX_CHANNUM_V30)) or ((nTargetType = 2) and (nTotalElements <= MAX_DISKNUM_V30)) then begin
len := nTotalElements * 4;
SetLength(channels,len);
bpt := @buff[140];
b1 := bpt[0];
b2 := bpt[1];
b3 := bpt[2];
b4 := bpt[3];
dwDataAddress := IntPtr(b1 + b2 * (1 shl 8) + b3 * (1 shl 16) + b4 * (1 shl 24));
sBuff := sBuff + IntToStr(dwDataAddress);
sBuff := sBuff + #10 + #13;
CopyMemory(Channels, @dwDataAddress, len);
I:=0;
while (i <= len - 4) do begin
sBuff := sBuff + 'Channel No: ' + IntToStr(channels[i]);
sBuff := sBuff + #13 + #10;
i:= i + 4;
end;
end;
end
end;
end;
有人可以重新检查翻译,因为 Delphi 代码没有重现与 C# 相同的结果。
更新:
阅读下面@Remy 写下的详细解释后,我能够在 C# 和 Delphi.
中的两个应用程序上重现相同的结果
现在可以使用的代码如下。
procedure ProcessCommAlarm_V40(pAlarmer: LPNET_DVR_ALARMER; pAlarmInfo: IntPtr; dwBufLen: DWORD; dwUser: IntPtr);
var
buff: array of byte;
channels: array of byte;
msgType: Integer;
sMsgType: String;
bAcceptedMsg: Boolean;
nTargetType: Integer;
sBuff: String;
nTotalElements: Integer;
len: Integer;
b1,b2,b3,b4:byte;
bpt: pbyte;
dwDataAddress: IntPtr;
I: Integer;
x:pbyte;
begin
Form1.Memo1.Lines.Add(FormatDateTime('H:m:s',now));
sBuff := '';
SetLength(buff, dwBufLen);
CopyMemory(buff, Pointer(pAlarmInfo), dwBufLen);
if (dwBufLen - 140 > 0) and ((dwBufLen - 140) mod 4 = 0) then begin
msgType := Integer(buff[0]);
sMsgType := '';
bAcceptedMsg := false;
nTargetType := 0;
case (msgType) of
2:
begin
sMsgType := 'Video loss';
bAcceptedMsg := true;
nTargetType := 1;
end;
end;
if (bAcceptedMsg) then
begin
nTotalElements := buff[12];
if ((nTargetType = 1) and (nTotalElements <= MAX_CHANNUM_V30)) or ((nTargetType = 2) and (nTotalElements <= MAX_DISKNUM_V30)) then begin
len := nTotalElements * 4;
SetLength(channels,len);
bpt := @buff[140];
b1 := bpt[0];
b2 := bpt[1];
b3 := bpt[2];
b4 := bpt[3];
dwDataAddress := IntPtr(b1 + b2 * (1 shl 8) + b3 * (1 shl 16) + b4 * (1 shl 24));
CopyMemory(Channels, Pointer(dwDataAddress), len);
I:=0;
while (i <= len - 4) do begin
sBuff := sBuff + 'Channel No: ' + IntToStr(channels[i]);
sBuff := sBuff + #13 + #10;
i:= i + 4;
end;
end;
end
end;
end;
给定 buff: array[0..MaxLimit] of Byte;
其中 MaxLimit >= 143;
在 Delphi 2009 年及以后:
var
bpt: PByte;
b1, b2, b3, b4: Byte;
begin
bpt := @buff[140];
b1 := bpt[0];
b2 := bpt[1];
b3 := bpt[2];
b4 := bpt[3];
end;
2007 年 Delphi 及更早版本:
var
bpt: PChar;
b1, b2, b3, b4: Byte;
begin
bpt := PChar(@buff[140]);
b1 := Byte(bpt[0]);
b2 := Byte(bpt[1]);
b3 := Byte(bpt[2]);
b4 := Byte(bpt[3]);
end;
或者:
var
bpt: PByte;
b1, b2, b3, b4: Byte;
begin
bpt := @buff[140];
b1 := bpt^; Inc(bpt);
b2 := bpt^; Inc(bpt);
b3 := bpt^; Inc(bpt);
b4 := bpt^; Inc(bpt);
end;
更新:话虽如此,我发现您的翻译存在一些问题。
在C#代码中,dwUser
参数被声明为IntPtr
,这是一个指针大小的整数。 Delphi 还有 IntPtr
。但是在您的 Delphi 代码中,您已将参数声明为 DWORD
。这将适用于 32 位版本,但不适用于 64 位版本。如果参数收到超过 32 位的值,如内存地址,它将被截断。如果不是 IntPtr
.
,请改用 DWORD_PTR
在C#代码中,pAlarmInfo
参数声明为IntPtr
。但是在您的 Delphi 代码中,您已将参数声明为 PChar
。虽然 可以 工作,但如果不是 IntPtr
.
,则无类型的 Pointer
会更合适
在Delphi中,使用array of bytes
对于buff
和channels
变量是可以的,尽管TBytes
或TArray<Byte>
在现代 Delphi 版本中更受欢迎。
使用 Win32 CopyMemory()
函数没问题,但您应该考虑使用 Delphi 的 System.Move()
。在任何情况下,您对 CopyMemory()
的第一次调用都是正确的(但是,如果 pAlarmInfo
被声明为 IntPtr
,您将必须将其类型转换为 Pointer
)。但是,您的第二次通话是错误的。 C# 代码正在从 dwDataAddress
中保存的内存地址复制 len
字节,而您正在从 dwDataAddress
本身的地址复制 len
字节。您需要将 dwDataAddress
类型转换为指针并从指向的地址复制。
你对msgType
和nTotalElements
赋值的翻译是错误的。 C# 代码分别从索引 0..3
和 12..15
处的 buff
中提取 4 字节整数 。您的 Delphi 代码正在读取索引 12
和 15
处的 1 字节 ,并将它们的值扩展到 Integer
。不是一回事。
您完全省略了 case msgType of
语句中的 3
大小写。可能是因为它没有设置 bAcceptedMsg = true
。我怀疑缺少赋值可能是 C# 代码中的错误。
#10 + #13
应该是 #13 + #10
,或者只是 #13#10
。或者,您应该改用 Delphi 的 System.sLineBreak
常量。
你对 channel
数字的翻译是错误的。如上文所述,C# 代码分别从索引 i..i+3
处的 channels
中提取 4 字节整数 。您的 Delphi 代码正在读取索引 i
处的 1 字节 并将其值扩展到 Integer
.
我需要帮助将部分 C# 代码翻译成 Delphi。 如果有任何帮助或建议,我将不胜感激。
unsafe {
fixed (byte* bpt = &buff[140]) {
byte b1 = bpt[0];
byte b2 = bpt[1];
byte b3 = bpt[2];
byte b4 = bpt[3];
}
}
我尝试了几种方法,用 4 字节变量定义记录,定义 tbytearray,但似乎都不对。
对此有什么想法吗?
谢谢。
更新
看来我的问题没有定义好,因为这是我的第一个问题,这里是C#上的完整函数。
private void ProcessCommAlarm_V40(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
{
MyDebugInfo AlarmInfo = new MyDebugInfo(DebugInfo);
byte[] buff = new byte[dwBufLen];
System.Runtime.InteropServices.Marshal.Copy(pAlarmInfo, buff, 0, (int)dwBufLen);
string sBuff = "";
if (dwBufLen - 140 > 0 && (dwBufLen - 140) % 4 == 0)
{
int msgType = BitConverter.ToInt32(buff, 0);
string sMsgType = "";
bool bAcceptedMsg = false;
int nTargetType = 0;
switch (msgType)
{
case 2:
sMsgType = "Video Loss"; bAcceptedMsg = true; nTargetType = 1; break;
case 3:
sMsgType = "Motion"; nTargetType = 1; break;
}
if (bAcceptedMsg)
{
int nTotalElements = BitConverter.ToInt32(buff, 12);
if ((nTargetType == 1 && nTotalElements <= CHCNetSDK.MAX_CHANNUM_V30) || (nTargetType == 2 && nTotalElements <= CHCNetSDK.MAX_DISKNUM_V30))
{
int len = nTotalElements * 4;
byte[] channels = new byte[len];
unsafe
{
fixed (byte* bpt = &buff[140])
{
byte b1 = bpt[0];
byte b2 = bpt[1];
byte b3 = bpt[2];
byte b4 = bpt[3];
IntPtr dwDataAddress = new IntPtr(b1 + b2 * (1 << 8) + b3 * (1 << 16) + b4 * (1 << 24));
System.Runtime.InteropServices.Marshal.Copy(dwDataAddress, channels, 0, len);
}
}
for (int i = 0; i <= len - 4; i += 4)
{
sBuff += string.Format("Channel No: {0}", BitConverter.ToInt32(channels, i));
sBuff += Environment.NewLine;
}
}
}
}
}
现在,这就是我到目前为止所做的,其中包括给我的 @remy-lebeau 所做的更改。
procedure ProcessCommAlarm_V40(pAlarmer: LPNET_DVR_ALARMER; pAlarmInfo: PChar; dwBufLen: DWORD; dwUser: DWORD);
var
buff: array of byte;
msgType: Integer;
sMsgType: String;
bAcceptedMsg: Boolean;
nTargetType: Integer;
sBuff: String;
nTotalElements: Integer;
channels: array of byte;
len: Integer;
b1,b2,b3,b4:byte;
bpt: pbyte;
dwDataAddress: IntPtr;
I: Integer;
begin
sBuff := '';
SetLength(buff, dwBufLen);
CopyMemory(buff, pAlarmInfo, dwBufLen);
if (dwBufLen - 140 > 0) and ((dwBufLen - 140) mod 4 = 0) then begin
msgType := Integer(buff[0]);
sMsgType := '';
bAcceptedMsg := false;
nTargetType := 0;
case (msgType) of
2:
begin
sMsgType := 'Video loss';
bAcceptedMsg := true;
nTargetType := 1;
end;
end;
if (bAcceptedMsg) then
begin
nTotalElements := buff[12];
if ((nTargetType = 1) and (nTotalElements <= MAX_CHANNUM_V30)) or ((nTargetType = 2) and (nTotalElements <= MAX_DISKNUM_V30)) then begin
len := nTotalElements * 4;
SetLength(channels,len);
bpt := @buff[140];
b1 := bpt[0];
b2 := bpt[1];
b3 := bpt[2];
b4 := bpt[3];
dwDataAddress := IntPtr(b1 + b2 * (1 shl 8) + b3 * (1 shl 16) + b4 * (1 shl 24));
sBuff := sBuff + IntToStr(dwDataAddress);
sBuff := sBuff + #10 + #13;
CopyMemory(Channels, @dwDataAddress, len);
I:=0;
while (i <= len - 4) do begin
sBuff := sBuff + 'Channel No: ' + IntToStr(channels[i]);
sBuff := sBuff + #13 + #10;
i:= i + 4;
end;
end;
end
end;
end;
有人可以重新检查翻译,因为 Delphi 代码没有重现与 C# 相同的结果。
更新:
阅读下面@Remy 写下的详细解释后,我能够在 C# 和 Delphi.
中的两个应用程序上重现相同的结果现在可以使用的代码如下。
procedure ProcessCommAlarm_V40(pAlarmer: LPNET_DVR_ALARMER; pAlarmInfo: IntPtr; dwBufLen: DWORD; dwUser: IntPtr);
var
buff: array of byte;
channels: array of byte;
msgType: Integer;
sMsgType: String;
bAcceptedMsg: Boolean;
nTargetType: Integer;
sBuff: String;
nTotalElements: Integer;
len: Integer;
b1,b2,b3,b4:byte;
bpt: pbyte;
dwDataAddress: IntPtr;
I: Integer;
x:pbyte;
begin
Form1.Memo1.Lines.Add(FormatDateTime('H:m:s',now));
sBuff := '';
SetLength(buff, dwBufLen);
CopyMemory(buff, Pointer(pAlarmInfo), dwBufLen);
if (dwBufLen - 140 > 0) and ((dwBufLen - 140) mod 4 = 0) then begin
msgType := Integer(buff[0]);
sMsgType := '';
bAcceptedMsg := false;
nTargetType := 0;
case (msgType) of
2:
begin
sMsgType := 'Video loss';
bAcceptedMsg := true;
nTargetType := 1;
end;
end;
if (bAcceptedMsg) then
begin
nTotalElements := buff[12];
if ((nTargetType = 1) and (nTotalElements <= MAX_CHANNUM_V30)) or ((nTargetType = 2) and (nTotalElements <= MAX_DISKNUM_V30)) then begin
len := nTotalElements * 4;
SetLength(channels,len);
bpt := @buff[140];
b1 := bpt[0];
b2 := bpt[1];
b3 := bpt[2];
b4 := bpt[3];
dwDataAddress := IntPtr(b1 + b2 * (1 shl 8) + b3 * (1 shl 16) + b4 * (1 shl 24));
CopyMemory(Channels, Pointer(dwDataAddress), len);
I:=0;
while (i <= len - 4) do begin
sBuff := sBuff + 'Channel No: ' + IntToStr(channels[i]);
sBuff := sBuff + #13 + #10;
i:= i + 4;
end;
end;
end
end;
end;
给定 buff: array[0..MaxLimit] of Byte;
其中 MaxLimit >= 143;
在 Delphi 2009 年及以后:
var
bpt: PByte;
b1, b2, b3, b4: Byte;
begin
bpt := @buff[140];
b1 := bpt[0];
b2 := bpt[1];
b3 := bpt[2];
b4 := bpt[3];
end;
2007 年 Delphi 及更早版本:
var
bpt: PChar;
b1, b2, b3, b4: Byte;
begin
bpt := PChar(@buff[140]);
b1 := Byte(bpt[0]);
b2 := Byte(bpt[1]);
b3 := Byte(bpt[2]);
b4 := Byte(bpt[3]);
end;
或者:
var
bpt: PByte;
b1, b2, b3, b4: Byte;
begin
bpt := @buff[140];
b1 := bpt^; Inc(bpt);
b2 := bpt^; Inc(bpt);
b3 := bpt^; Inc(bpt);
b4 := bpt^; Inc(bpt);
end;
更新:话虽如此,我发现您的翻译存在一些问题。
在C#代码中,
,请改用dwUser
参数被声明为IntPtr
,这是一个指针大小的整数。 Delphi 还有IntPtr
。但是在您的 Delphi 代码中,您已将参数声明为DWORD
。这将适用于 32 位版本,但不适用于 64 位版本。如果参数收到超过 32 位的值,如内存地址,它将被截断。如果不是IntPtr
.DWORD_PTR
在C#代码中,
,则无类型的pAlarmInfo
参数声明为IntPtr
。但是在您的 Delphi 代码中,您已将参数声明为PChar
。虽然 可以 工作,但如果不是IntPtr
.Pointer
会更合适在Delphi中,使用
array of bytes
对于buff
和channels
变量是可以的,尽管TBytes
或TArray<Byte>
在现代 Delphi 版本中更受欢迎。使用 Win32
CopyMemory()
函数没问题,但您应该考虑使用 Delphi 的System.Move()
。在任何情况下,您对CopyMemory()
的第一次调用都是正确的(但是,如果pAlarmInfo
被声明为IntPtr
,您将必须将其类型转换为Pointer
)。但是,您的第二次通话是错误的。 C# 代码正在从dwDataAddress
中保存的内存地址复制len
字节,而您正在从dwDataAddress
本身的地址复制len
字节。您需要将dwDataAddress
类型转换为指针并从指向的地址复制。你对
msgType
和nTotalElements
赋值的翻译是错误的。 C# 代码分别从索引0..3
和12..15
处的buff
中提取 4 字节整数 。您的 Delphi 代码正在读取索引12
和15
处的 1 字节 ,并将它们的值扩展到Integer
。不是一回事。您完全省略了
case msgType of
语句中的3
大小写。可能是因为它没有设置bAcceptedMsg = true
。我怀疑缺少赋值可能是 C# 代码中的错误。#10 + #13
应该是#13 + #10
,或者只是#13#10
。或者,您应该改用 Delphi 的System.sLineBreak
常量。你对
channel
数字的翻译是错误的。如上文所述,C# 代码分别从索引i..i+3
处的channels
中提取 4 字节整数 。您的 Delphi 代码正在读取索引i
处的 1 字节 并将其值扩展到Integer
.