Reputation: 294
I'm trying translate a piece of code from C to Delphi, that have as goal fill a struct until max limit allowed previous defined. I tried make the Delphi version more near of C code (even so not be a professional programmer).
But i noted that in my Delphi code the seems struct is filled only with 0 values (result of FillMemory()
) and not is being filled with correct values.
How i can solve it? below i show only the relevant code.
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;
Upvotes: 0
Views: 92
Reputation: 595377
You have shown no code, on either the C side or the Delphi side, that actually tries to fill the array with data. Looking at the original C code, it populates a found array element with data inside of the ClientThread()
function. You didn't translate those pieces of C code, which explains why the array in your Delphi code has no data in it:
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;
}
In any case, your translation is close to the C code you did show, but not entirely correct, particularly in regards to the Client
record. You are not declaring the members in the same order that the C code does. And Delphi's Boolean
is not the same type as C's BOOL
. Delphi's equivalent is LongBool
instead (Delphi has a BOOL
alias for LongBool
).
Try this instead:
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;
Upvotes: 1