intendi come piattaforma?
medium italia + youtube per video?
Edit:
https://medium.com/italia
Se il server del forum regge, mettere un sottodominio e worpress collegato al sottodominio?Non è un server virtuale, a un servizio di hosting
Senza partire da zero intendo.
Stilgar
comunque wordpress e blogspot sono gratuiti
suggerisco di unificare le installazioni Windows sotto una unica categoria
direi che tanto per iniziare, sul sito del forum ci metterei un link al blog 8)
Edit:
propongo di aggiungere sotto al box "Forum ufficiale", un box "Blog"
che ne dite?
direi che tanto per iniziare, sul sito del forum ci metterei un link al blog 8)
Edit:
propongo di aggiungere sotto al box "Forum ufficiale", un box "Blog"
che ne dite?
Fatto, ma sopra non sotto.
Ma ho fatto entrambidirei che tanto per iniziare, sul sito del forum ci metterei un link al blog 8)
Edit:
propongo di aggiungere sotto al box "Forum ufficiale", un box "Blog"
che ne dite?
Fatto, ma sopra non sotto.
Si intendeva un link DAL FORUM AL BLOG .... comunque il link dal BLOG al FORUM và bene ... ;D
nuovo articolo sul blog di FpDebugger: il nuovo debugger made in Lazarus e Free PascalL' FPDebugger è settato di base se installi Lazarus ex novo, almeno in Windows, (sia come pacchetto ovviamento che come debugger di default).
nuovo articolo su code templates
https://blog.lazaruspascal.it/2022/01/25/code-templates/ (https://blog.lazaruspascal.it/2022/01/25/code-templates/)
nuovo articolo su code templates
Ciao a tutti, volevo solo avvisare che ho appena pubblicato un post sul blog intitolato: lazarus e android (primi passi)
altro articolo
si tratta dell'installazione di PAS2JS
https://blog.lazaruspascal.it/2022/04/15/pas2js-installazione/ (https://blog.lazaruspascal.it/2022/04/15/pas2js-installazione/)
buona lettura
Ottimo, grazie!Grazie per la segnalazione, aggiornati anche ulteriori "refusi" ... la domenica influisce negativamente sulla stesura degli articoli ..... ;)
PS
Un piccolissimo refuso: affinty invece di affinity più o meno a metà
altro articolo, un primo progetto con Pas2Js
https://blog.lazaruspascal.it/2022/05/25/pas2js-tutorial-1-progetto-login-html-statico-scritto-a-mano/
spero vi piaccia :)
25/05/2022 20:28 <DIR> backup
22/05/2022 17:50 <DIR> js
22/05/2022 18:43 1.419 project_login.html
24/05/2022 09:36 91.347 project_login.js
24/05/2022 09:36 904.601 project_login.js.map
24/05/2022 09:36 2.629 project_login.lpi
24/05/2022 09:36 1.501 project_login.lpr
25/05/2022 20:28 4.821 project_login.lps
il .js lo si genera quando si compila
cioè da menù: Esegui -> Costruisci (o Run -> Execute se hai il menù in inglese)
dopo compilato dovresti avere nella cartella del progetto qualcosa del genere
il file project_login.lpr è il file del progetto pascal
il file project_login.js è il "prodotto" della compilazione di Pas2Js
grazie xinyiman :)Lo sai che se dici così mi tocca fremere nell'attesa
il prossimo che ho in mente è sempre su pas2js ma, se riesco, sarà un tutorial su un uso meno accademico e molto più pratico
ci vorrà un po' di tempo ma spero di fare una cosa interessante
nomorelogic
Bello, e solo con i componenti di FPC ;D
Per le librerie SSL, ti indirizzerei qui: https://github.com/IndySockets/OpenSSL-Binaries (https://github.com/IndySockets/OpenSSL-Binaries)
E' il repository di Indy, sono testate e funzionanti.
La 1.0.2u è l'ultima versione della release 1.0, supporta fino a TLS 1.2
Ciao
Gli articoli riguardanti le interfacce sono stati inseriti anche nel Blog: https://blog.lazaruspascal.it/2023/09/25/interfacce-interface-parte-1/ (https://blog.lazaruspascal.it/2023/09/25/interfacce-interface-parte-1/)
Ciao
Un suggerimento per un ulteriore capitolo della serie: potrebbe essere interessante descrivere la modalità {$interfaces corba} di FPC.
Io la uso praticamente sempre e penso che porti la funzionalità delle interfacce in Lazarus/FPC una spanna sopra quella di Delphi, con un comportamento che è in linea con quello di tutti gli altri linguaggi di programmazione che implementano le interfacce.
Ultima cosa: Nick Hodges non lavora più per Embarcadero da un bel po', credo sia caduto in disgrazia ai tempi in cui hanno poi deciso di affidare la direzione dello sviluppo di Delphi a Marco Cantù.Nick Hodges lasciò Embarcadero nel 2010 nel periodo del "rapido balletto" tra Borland / Inprise / Codgear / Embarcadero (2006 / 2008).
Un suggerimento per un ulteriore capitolo della serie: potrebbe essere interessante descrivere la modalità {$interfaces corba} di FPC.
Io la uso praticamente sempre e penso che porti la funzionalità delle interfacce in Lazarus/FPC una spanna sopra quella di Delphi, con un comportamento che è in linea con quello di tutti gli altri linguaggi di programmazione che implementano le interfacce.
Su suggerimento di @nomorelogic : https://castle-engine.io/modern_pascal#_interfaces (https://castle-engine.io/modern_pascal#_interfaces)
Senza attivare quello switch le interfacce sono di tipo COM e, fondamentalmente, come già spiegato nei post di DragoRosso, hanno il reference counting.
Usando lo switch {$interfaces corba} non si ha a disposizione il reference counting (e di conseguenza il sistema automatico di liberazione delle risorse) ma si ha a disposizione la possibilità di definire interfacce ad un livello più astratto, simile all'ereditarietà multipla e utile per la definizione di API.
//Definizione di per l'uso delle interfacce senza reference counting
type
TInterfaceedObjectNoRFC = class(TInterfacedObject, IInterface)
protected
function _AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
function _Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
end;
implementation
function TInterfaceedObjectNoRFC._AddRef: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
begin
Result := -1;
end;
function TInterfaceedObjectNoRFC._Release: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
begin
Result := -1;
end;
ognuno di noi ha il suo modo di interpretare la programmazione ovviamente :)Si, si, non volevo polemizzare assolutamente. La mia intenzione era fornire un'altra vista "standardizzata" per l'argomento "reference counting". Ovvio che siamo fortunatamente in un mondo libero (magari non proprio tutto ::) ) e ognuno come sottolinei tu fa ciò ritiene opportuno.
quello switch non è una scorciatoia ma un modo diverso di intendere le interfacce e, dal mio punto di vista, _AddRef e _Release (se ne parla anche nel link tra l'altro) non è detto che siano indispensabili: sono delle possibilità
quindi le funzionalità a disposizione in uno strumento di sviluppo, è corretto che vengano elencate completamente
poi sta ad ogni sviluppatore vederci e farci quello che vuole :)
Spero sia utile
bella l'idea di adottare animaletti alieni ;D
program restfulhttpserverthreadsafe;
{$mode objfpc}{$H+}
{$define THREADPOOL}
{
This code has been dedicated to the public domain.
You may use, modify, copy, or distribute this code freely,
for any purpose, without any conditions or warranties.
Author: nomorelogic (Basso Marcello)
Date: 13/05/2025
Special thanks to (https://forum.lazarus.freepascal.org/index.php/topic,71031.0.html):
- Thaddy
- Fibonacci
Abstract:
this code is an intentionally simple version of a microservice for a restful json server
is intended to be a basis for creating better servers
}
uses
cthreads,
Classes,
SysUtils,
cmem,
libmicrohttpd,
fpjson,
jsonparser,
syncobjs;
const
PORT = 8888;
type
TRestResponse = record
StatusCode: cuint;
ResText: string;
end;
TClientContextInfo = record
Playload_AsText: string;
PlayLoadIsJson: boolean;
PlayLoad_AsJson: TJSONObject;
Response: TRestResponse;
end;
PClientContextInfo = ^TClientContextInfo;
var
ShouldStop: boolean = False;
Daemon: PMHD_Daemon;
StopLock: TCriticalSection;
function HandleRestfulRequest(cls: Pointer; connection: PMHD_Connection;
url, method, version: pchar; upload_data: pchar; upload_data_size: pSize_t;
con_cls: PPointer): cint; cdecl;
var
response: PMHD_Response;
jsonObj: TJSONObject;
con_info: PClientContextInfo;
begin
Result := 0;
// - - - - - - - - - - - - - - - - - - - - - - -
// first call
// the first invocation is used to initialize the
// context of the request; generally a data structure is created
// - - - - - - - - - - - - - - - - - - - - - - -
if con_cls^ = nil then
begin
// init client context
New(con_info);
con_info^.Playload_AsText := '';
con_info^.PlayLoadIsJson := False;
con_info^.PlayLoad_AsJson := nil;
con_info^.Response.StatusCode := MHD_HTTP_OK;
con_info^.Response.ResText := '';
con_cls^ := con_info;
Exit(MHD_YES);
end; // else begin
con_info := PClientContextInfo(con_cls^);
// - - - - - - - - - - - - - - - - - - - - - - -
// Handle POST data
// in the case of POST data: an additional callback
// is executed to allow the input data to be handled
// - - - - - - - - - - - - - - - - - - - - - - -
if (method = MHD_HTTP_METHOD_POST) and (upload_data_size^ <> 0) then
begin
SetString(con_info^.Playload_AsText, upload_data, upload_data_size^);
// Try to parse as JSON if content-type is application/json
if Assigned(MHD_lookup_connection_value(connection, MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONTENT_TYPE)) then
if (Pos('application/json',
MHD_lookup_connection_value(connection, MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONTENT_TYPE)) > 0) then
begin
if con_info^.Playload_AsText <> '' then
try
con_info^.PlayLoadIsJson := True;
con_info^.PlayLoad_AsJson :=
GetJSON(con_info^.Playload_AsText) as TJSONObject;
except
// on exception: return error
con_info^.Response.StatusCode := MHD_HTTP_INTERNAL_SERVER_ERROR;
con_info^.Response.ResText := '{"error": "Invalid JSON format"}';
end;
end;
upload_data_size^ := 0;
Exit(MHD_YES);
end; // <-- handle post data
// - - - - - - - - - - - - - - - - - - - - - - -
// last call
// response handler
// - - - - - - - - - - - - - - - - - - - - - - -
if con_info^.Response.StatusCode = MHD_HTTP_OK then
begin
if url = '/shutdown' then
begin
jsonObj := TJSONObject.Create;
jsonObj.Add('status', 'shutting down');
con_info^.Response.ResText := jsonObj.AsJSON;
jsonObj.Free;
// try gracefully stop
StopLock.Enter;
try
ShouldStop := True;
finally
StopLock.Leave;
end;
end
else if (url = '/api/status') and (method = 'GET') then
begin
jsonObj := TJSONObject.Create;
jsonObj.Add('status', 'ok');
jsonObj.Add('uptime', FormatDateTime('hh:nn:ss', Now));
con_info^.Response.ResText := jsonObj.AsJSON;
jsonObj.Free;
end
else if url = '/api/echo' then
begin
if method = 'GET' then
begin
con_info^.Response.ResText := '{"method": "GET", "data": "echo"}';
end
else if method = 'POST' then
begin
// do we have a playload?
if con_info^.PlayLoadIsJson then
begin
if Assigned(con_info^.PlayLoad_AsJson) then
con_info^.Response.ResText := con_info^.PlayLoad_AsJson.AsJSON;
end
else
begin
con_info^.Response.ResText := con_info^.Playload_AsText;
end;
// playload is empty?
if con_info^.Response.ResText = '' then
begin
con_info^.Response.StatusCode := MHD_HTTP_NO_CONTENT;
con_info^.Response.ResText := '{"error": "No data received"}';
end;
end;
end; // POST /api/echo
end; // <-- second call
// - - - - - - - - - - - - - - - - - - - - -
// response
// send respnse and free resources
// - - - - - - - - - - - - - - - - - - - - -
response := MHD_create_response_from_buffer(Length(con_info^.Response.ResText),
PChar(con_info^.Response.ResText), MHD_RESPMEM_MUST_COPY);
MHD_add_response_header(response, 'Content-Type', 'application/json');
Result := MHD_queue_response(connection, con_info^.Response.StatusCode, response);
// Free response
MHD_destroy_response(response);
// Free client context
if Assigned(con_info^.PlayLoad_AsJson) then
con_info^.PlayLoad_AsJson.Free;
Dispose(con_info);
con_cls^ := nil;
end; // function HandleRestfulRequest
begin
// critical section
StopLock := TCriticalSection.Create;
try
// Create the MHD daemon with either thread pool OR thread-per-connection
// Choose one of these options:
// Option 1: Thread pool (fixed number of threads)
{$if Defined(THREADPOOL)}
Daemon := MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD or
MHD_USE_DEBUG, PORT, nil, nil, @HandleRestfulRequest,
nil, MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
{$else thread_per_connection}
// Option 2: Thread-per-connection (one thread per request)
Daemon := MHD_start_daemon(
MHD_USE_THREAD_PER_CONNECTION or MHD_USE_DEBUG or MHD_USE_INTERNAL_POLLING_THREAD,
PORT,
nil,
nil,
@HandleRestfulRequest,
nil,
MHD_OPTION_END
);
{$ifend}
if Daemon = nil then
begin
WriteLn('Error starting HTTP server!');
Halt(1);
end;
WriteLn('rest server started at: http://localhost:', PORT);
WriteLn('Endpoints: /api/status (GET), /api/echo (POST), /shutdown');
// Loop server
while not ShouldStop do
Sleep(100);
MHD_stop_daemon(Daemon);
WriteLn('Server stopped.');
finally
StopLock.Free;
end;
end.
echo "request: GET status"
curl -X GET -H "Content-Type: application/json" http://localhost:8888/api/status
echo "<<"
echo "request: GET echo"
curl -X GET -H "Content-Type: application/json" http://localhost:8888/api/echo
echo "<<"
echo "request: POST echo"
curl -X POST -H "Content-Type: application/json" -d '{"message": "hello from client"}' http://localhost:8888/api/echo
echo "<<"
echo "request: shutdown"
curl -X GET -H "Content-Type: application/json" http://localhost:8888/shutdown
echo "<<"