微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 C# 到 Delphi 的翻译

如何解决从 C# 到 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,(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,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,b4:byte;
  bpt: pbyte;
  dwDataAddress: IntPtr;
  I: Integer;
  x:pbyte;
begin
  Form1.Memo1.Lines.Add(FormatDateTime('H:m:s',Now));
  sBuff := '';

  SetLength(buff,Pointer(pAlarmInfo),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;

在 Delphi 2007 及更早版本中:

var
  bpt: PChar;
  b1,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,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 位的值,例如内存地址,它将被截断。如果不是 DWORD_PTR,请改用 IntPtr

  • 在 C# 代码中,pAlarmInfo 参数声明为 IntPtr。但是在您的 Delphi 代码中,您已将参数声明为 PChar。尽管 可以 工作,但如果不是 Pointer,无类型的 IntPtr 会更合适。

  • 在 Delphi 中,对 array of bytesbuff 变量使用 channels 是可以的,尽管 TBytesTArray<Byte> 在现代更受欢迎Delphi 版本。

  • 使用 Win32 CopyMemory() 函数没问题,但您应该考虑使用 Delphi 的 System.Move() 代替。在任何情况下,您对 CopyMemory() 的第一次调用都是正确的(不过,如果 pAlarmInfo 被声明为 IntPtr,则您必须将其类型转换为 Pointer)。但是,您的第二个电话是错误的。 C# 代码从 len 中保存的内存地址复制 dwDataAddress 字节,而您从 len 本身的地址复制 dwDataAddress 字节。您需要将 dwDataAddress 类型转换为指针并从指向的地址复制。

  • 您对 msgTypenTotalElements 的赋值的翻译是错误的。 C# 代码分别从索引 buff0..3 处的 12..15 中提取 4 字节整数。您的 Delphi 代码正在索引 1215 处读取 1 个字节,并将它们的值缩放到 Integer。不是一回事。

  • 您在 3 语句中完全省略了 case case msgType of。可能是因为它没有设置 bAcceptedMsg = true。我怀疑缺少赋值可能是 C# 代码中的错误。

  • #10 + #13 应该是 #13 + #10,或者只是 #13#10。或者,您应该改用 Delphi 的 System.sLineBreak 常量。

  • 您对 channel 数字的翻译是错误的。与上面进一步类似,C# 代码分别从索引 channels 处的 i..i+3 中提取 4 字节整数。您的 Delphi 代码正在索引 i 处读取 1 个字节并将其值缩放到 Integer

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?