#delphi #record #delphi-10-seattle
#delphi #запись #delphi-10-Сиэтл
Вопрос:
Я пытаюсь перевести фрагмент кода с C на Delphi, целью которого является заполнение структуры до максимально допустимого предела, определенного ранее. Я попытался сделать версию Delphi более близкой к C-коду (даже если это не профессиональный программист).
Но я отметил, что в моем коде на Delphi кажется, что структура заполнена только значениями 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 amp;g_clients[i];
}
else
{
if(g_clients[i].hWnd == (HWND) data)
return amp;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 = amp;g_clients[i];
}
}
if(!found)
{
wprintf(TEXT("User %S kicked max %d usersn"), "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. Похоже, это ответ, почему ваш getClient вернул nil в вашем предыдущем (удаленном) вопросе.
Ответ №1:
Вы не показали никакого кода ни на стороне 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 *) amp;client->screenWidth, sizeof(client->screenWidth), 0) <= 0)
goto exit;
if(recv(s, (char *) amp;client->screenHeight, sizeof(client->screenHeight), 0) <= 0)
goto exit;
...
if(client->pixels amp;amp; client->pixelsWidth == ... amp;amp; 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 = amp;g_clients[i];
}
}
if(!found)
{
wprintf(TEXT("User %S kicked max %d usersn"), 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;