Estou desenvolvendo algumas ferramentas para Linux usando o Delphi Tokyo e tive o problema de não conseguia de forma alguma fazer chamadas e comandos externos.
Mas isso ainda não me era suficiente pois a forma que o código estava implementado me forçava a usar um tal de MarshaledString.
Consegui fazer um codigo bacana depois de umas horas testando e batendo no código (a vontade não falta quando não funciona como a gente quer)
Vou compartilhar com vocês pois foi bem complicado ter essa informação e difícil de acha-la
uses
System.SysUtils,
System.Classes,
Posix.Base,
Posix.Fcntl;
type
TStreamHandle = pointer;
TLinuxUtils = class
public
class function RunCommandLine(ACommand : string) : TStringList;overload;
class function RunCommandLine(Acommand : string; Return : TProc<String>) : boolean; overload;
end;
function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl; external libc name _PU + 'popen';
function pclose(filehandle: TStreamHandle): int32; cdecl; external libc name _PU + 'pclose';
function fgets(buffer: pointer; size: int32; Stream: TStreamHAndle): pointer; cdecl; external libc name _PU + 'fgets';
implementation
class function TLinuxUtils.RunCommandLine(ACommand : string) : TStringList;
var
Handle: TStreamHandle;
Data: array[0..511] of uint8;
M : TMarshaller;
begin
Result := TStringList.Create;
try
Handle := popen(M.AsAnsi(PWideChar(ACommand)).ToPointer,'r');
try
while fgets(@data[0],Sizeof(Data),Handle)<>nil do begin
Result.Add(Copy(UTF8ToString(@Data[0]),1,UTF8ToString(@Data[0]).Length -1));
end;
finally
pclose(Handle);
end;
except
on E: Exception do
Result.Add(E.ClassName + ': ' + E.Message);
end;
end;
class function TLinuxUtils.RunCommandLine(Acommand : string; Return : TProc<string>) : boolean;
var
Handle: TStreamHandle;
Data: array[0..511] of uint8;
M : TMarshaller;
begin
Result := false;
try
Handle := popen(M.AsAnsi(PWideChar(ACommand)).ToPointer,'r');
try
while fgets(@data[0],Sizeof(Data),Handle)<>nil do begin
Return(Copy(UTF8ToString(@Data[0]),1,UTF8ToString(@Data[0]).Length -1));
end;
finally
pclose(Handle);
end;
except
on E: Exception do
Return(E.ClassName + ': ' + E.Message);
end;
end;