C to Delphi: struct not 被填充

C to Delphi: Struct not is filled

我正在尝试将一段代码从 C 翻译成 Delphi,其目标是填充一个结构,直到先前定义的最大限制允许为止。我试着让 Delphi 版本更接近 C 代码(即使不是专业程序员)。

但我注意到,在我的 Delphi 代码中,seems 结构仅填充了 0 个值(FillMemory() 的结果),而没有填充正确的值。

我该如何解决?下面我只显示相关代码。

C: (code of reference)

struct Client
{
   SOCKET connections[2];
   DWORD  uhid;
   HWND   hWnd;
   BYTE  *pixels;
   DWORD  pixelsWidth, pixelsHeight;
   DWORD  screenWidth, screenHeight;
   HDC    hDcBmp;
   HANDLE minEvent;
   BOOL   fullScreen;
   RECT   windowedRect;
};

static Client g_clients[256];


static Client *GetClient(void *data, BOOL uhid)
{
   for(int i = 0; i < 256; ++i)
   {
      if(uhid)
      {
         if(g_clients[i].uhid == (DWORD) data)
            return &g_clients[i];
      }
      else
      {
         if(g_clients[i].hWnd == (HWND) data)
            return &g_clients[i];
      }
   }
   return NULL;
}

BOOL recordClient()
{
  Client *client = NULL;
  BOOL   found = FALSE;
  DWORD  uhid;


uhid = 27650; // Some value, only as example here
memset(g_clients, 0, sizeof(g_clients));

client = GetClient((void *) uhid, TRUE);

 if(client)
   return FALSE;

    for(int i = 0; i < 256; ++i)
    {
      if(!g_clients[i].hWnd)
      {
         found = TRUE;
         client = &g_clients[i];
      }
    }

    if(!found)
    {
      wprintf(TEXT("User %S kicked max %d users\n"), "185.242.4.203", 256);
      return FALSE;
    }

   return TRUE;
}

Delphi:

type
  PClient = ^Client;

  Client = record
    Connections: array [0 .. 1] of TSocket;
    uhId, 
    pixelsWidth, 
    pixelsHeight, 
    screenWidth, 
    screenHeight: Cardinal;
    _hWnd: HWND;
    Pixels: PByte;
    hDcBmp: HDC;
    minEvent: THandle;
    fullScreen: Boolean;
    windowRect: TRect;
  end;


var
  Clients: array [0 .. 255] of Client;

//...

function GetClient(Data: Pointer; uhId: Boolean): PClient;
var
  I: Integer;
begin
  Result := nil;
  for I := 0 to 255 do
  begin
    if uhId then
    begin
      if Clients[I].uhId = Cardinal(Data) then
      begin
        Result := @Clients[I];
        Break;
      end;
    end
    else
    begin
      if Clients[I]._hWnd = HWND(Data) then
      begin
        Result := @Clients[I];
        Break;
      end;
    end;
  end;
end;

function recordClient: Boolean;
var
  _client: PClient;
  _uhId: Cardinal;
  found: Boolean;
  I: Integer;
begin
  Result := True;

  FillMemory(@Clients, SizeOf(Clients), 0);

  _uhId := 27650; // Some value, only as example here
  _client := GetClient(@_uhId, True);

  if _client <> nil then
  begin
    Result := False;
    Exit;
  end;

  found := False;

  for I := 0 to 255 do
  begin
    if Clients[I]._hWnd = 0 then
    begin
      found := True;
      _client := @Clients[I];
    end;
  end;

  if not found then
  begin                                            
    Writeln(Format('Client %s rejected, max allowed is %d clients.' + #13,
      ['185.242.4.203', 256])); // Only example values
    Result := False;
    Exit;
  end;
end;

您没有在 C 端或 Delphi 端显示实际尝试用数据填充数组的代码。查看原始 C 代码,它使用 ClientThread() 函数内的数据填充找到的数组元素。你没有翻译那些 C 代码,这就解释了为什么你的 Delphi 代码中的数组没有数据:

static DWORD WINAPI ClientThread(PVOID param)
{
   Client    *client = NULL;
   SOCKET     s = (SOCKET) param;
   ...

   if(connection == Connection::desktop)
   {
      client = GetClient((void *) uhid, TRUE);
      if(!client)
      {
         closesocket(s);
         return 0;
      }
      client->connections[Connection::desktop] = s;

      ...

      for(;;)
      {
         ...

         if(recv(s, (char *) &client->screenWidth, sizeof(client->screenWidth), 0) <= 0)
            goto exit;
         if(recv(s, (char *) &client->screenHeight, sizeof(client->screenHeight), 0) <= 0)
            goto exit;
         ...

            if(client->pixels && client->pixelsWidth == ... && client->pixelsHeight == ...)
            {
               for(...)
               {
                  ...
                  client->pixels[i] = newPixels[i];
                  client->pixels[i + 1] = newPixels[i + 1];
                  client->pixels[i + 2] = newPixels[i + 2];
               }
               ...
            }
            else
            {
               free(client->pixels);
               client->pixels = newPixels;
            }

            ...
            DeleteDC(client->hDcBmp);
            client->pixelsWidth = width;
            client->pixelsHeight = height;
            client->hDcBmp = hDcBmp;

            ...
         }
         ...
      }
exit:
      ...
      return 0;
   }
   else if(connection == Connection::input)
   {
      ...

         client = GetClient((void *) uhid, TRUE);
         if(client)
         {
            closesocket(s);
            ...
            return 0;
         }
         ...

         BOOL found = FALSE;
         for(int i = 0; i < gc_maxClients; ++i)
         {
            if(!g_clients[i].hWnd)
            {
               found = TRUE;
               client = &g_clients[i];
            }
         }
         if(!found)
         {
            wprintf(TEXT("User %S kicked max %d users\n"), ip, gc_maxClients);
            closesocket(s);
            return 0;
         }

         client->hWnd = CW_Create(uhid, gc_minWindowWidth, gc_minWindowHeight);
         client->uhid = uhid;
         client->connections[Connection::input] = s;
         client->minEvent = CreateEventA(NULL, TRUE, FALSE, NULL);

      ...

         free(client->pixels);
         DeleteDC(client->hDcBmp);
         closesocket(client->connections[Connection::input]);
         closesocket(client->connections[Connection::desktop]);
         CloseHandle(client->minEvent);
         memset(client, 0, sizeof(*client)); 

      ...
   }
   return 0;
}

无论如何,您的翻译接近于您显示的 C 代码,但不完全正确,特别是关于 Client 记录。您没有按照与 C 代码相同的顺序声明成员。而Delphi的Boolean与C的BOOL不是同一类型。 Delphi 的等价物是 LongBool(Delphi 有 LongBoolBOOL 别名)。

试试这个:

type
  PClient = ^Client;
  Client = record
    Connections: array[0..1] of TSocket;
    uhId: DWORD;
    _hWnd: HWND;
    Pixels: PByte;
    pixelsWidth, pixelsHeight: DWORD;
    screenWidth, screenHeight: DWORD;
    hDcBmp: HDC;
    minEvent: THandle;
    fullScreen: BOOL;
    windowedRect: TRect;
  end;

var
  Clients: array[0..255] of Client;

function GetClient(Data: Pointer; uhId: Boolean): PClient;
var
  I: Integer;
begin
  for I := 0 to 255 do
  begin
    if uhId then
    begin
      if Clients[I].uhId = DWORD(Data) then
      begin
        Result := @Clients[I];
        Exit;
      end
      else
      begin
        if Clients[I]._hWnd = HWND(Data) then
        begin
          Result := @Clients[I];
          Exit;
        end;
      end;
    end;
  end;
  Result := nil;
end;

function recordClient: BOOL;
var
  _client: PClient;
  found: Boolean;
  uhId: DWORD;
  I: Integer;
begin
  ZeroMemory(@Clients, Sizeof(Clients));

  uhId := 27650; // Some value, only as example here
  _client := GetClient(Pointer(uhid), TRUE);

  if _client <> nil then
  begin
    Result := FALSE;
    Exit;
  end;

  found := False;

  for I := 0 to 255 do
  begin
    if Clients[i]._hWnd = 0 then
    begin
      found := True;
      _client := @Clients[i];
      Break;
    end;
  end;

  if not found then
  begin
    WriteLn(Format('Client %s rejected, max allowed is %d clients.', ['185.242.4.203', 256]));
    Result := FALSE;
    Exit;
  end;

  // TODO: populate _client here as needed...

  Result := TRUE;
end;