Клиент к Delphi: структура не заполнена - PullRequest
0 голосов
/ 25 апреля 2019

Я пытаюсь перевести часть кода из C в Delphi, целью которого является заполнение структуры до максимального предела, определенного ранее.Я пытался сделать версию Delphi ближе к коду C (даже не быть профессиональным программистом).

Но я заметил, что в моем Delphi-коде структура struct заполнена только 0 значениями (результат FillMemory())) и не заполняется правильными значениями.

Как я могу решить это?ниже я показываю только соответствующий код.

C: ( код ссылки )

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;

1 Ответ

1 голос
/ 25 апреля 2019

Вы не показали ни кода, ни на стороне 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 имеет псевдоним BOOL для LongBool).

Попробуйте вместо этого:

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;
...