<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Topics tagged with programming]]></title><description><![CDATA[A list of topics that have been tagged with programming]]></description><link>https://forum.androidiani.net/tags/programming</link><generator>RSS for Node</generator><lastBuildDate>Fri, 01 May 2026 02:09:07 GMT</lastBuildDate><atom:link href="https://forum.androidiani.net/tags/programming.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 22 Apr 2026 09:19:56 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Creare addon nativi per Node.js con .NET Native AOT: addio a Python e node-gyp]]></title><description><![CDATA[Da sempre, creare addon nativi per Node.js significava entrare nel mondo di C++ e node-gyp, con la necessità di installare Python, Visual Studio Build Tools e una serie di dipendenze che trasformavano il setup dell’ambiente in un’impresa. Il team di C# Dev Kit di Microsoft ha trovato una soluzione elegante: usare .NET Native AOT per produrre librerie condivise compatibili con l’interfaccia N-API di Node.js, scritte interamente in C#.In questo articolo vediamo come funziona questa tecnica, analizzando la struttura del progetto, il meccanismo di interop e i punti critici da tenere d’occhio in produzione.Perché Node.js supporta addon scritti in qualsiasi linguaggioUn addon nativo per Node.js è semplicemente una libreria condivisa (.dll su Windows, .so su Linux, .dylib su macOS) che esporta un punto di ingresso preciso: la funzione napi_register_module_v1. Node.js carica la libreria, chiama questa funzione e da quel momento il modulo è disponibile per JavaScript.L’interfaccia che rende tutto questo possibile è N-API (Node-API), una API C stabile e ABI-compatibile tra le versioni di Node.js. Questo significa che qualsiasi linguaggio in grado di produrre una shared library ed esportare una funzione C può diventare un addon Node.js — incluso C# compilato con Native AOT.Configurazione del progetto .NETIl file di progetto è sorprendentemente minimale:&lt;Project Sdk="Microsoft.NET.Sdk"&gt;
  &lt;PropertyGroup&gt;
    &lt;TargetFramework&gt;net10.0&lt;/TargetFramework&gt;
    &lt;PublishAot&gt;true&lt;/PublishAot&gt;
    &lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt;
  &lt;/PropertyGroup&gt;
&lt;/Project&gt;Due impostazioni chiave:PublishAot: abilita la compilazione Ahead-of-Time, producendo una shared library nativa invece di un assembly IL.AllowUnsafeBlocks: necessario per l’interop con N-API tramite function pointer e tipi non gestiti.Il punto di ingresso del moduloL’entry point usa l’attributo [UnmanagedCallersOnly], che istruisce il compilatore a generare una funzione C-callable con la firma esatta attesa da Node.js:[UnmanagedCallersOnly(
    EntryPoint = "napi_register_module_v1",
    CallConvs = [typeof(CallConvCdecl)])]
public static nint Init(nint env, nint exports)
{
    // Registrazione delle funzioni esposte
    return exports;
}Il tipo nint (native-sized integer) rappresenta gli handle opachi che N-API usa per riferirsi agli oggetti JavaScript. Non si tratta di puntatori diretti a memoria, ma di token gestiti dall’engine V8 tramite N-API.Risoluzione delle funzioni N-API a runtimeLe funzioni N-API (come napi_create_string_utf8 o napi_get_cb_info) sono esportate direttamente da node.exe, non da una DLL separata. Per fare in modo che P/Invoke le risolva correttamente, si registra un custom resolver:private static void Initialize()
{
    NativeLibrary.SetDllImportResolver(
        System.Reflection.Assembly.GetExecutingAssembly(),
        ResolveDllImport);
}

private static nint ResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
    if (libraryName == "node")
        return NativeLibrary.GetMainProgramHandle();
    return IntPtr.Zero;
}Questo permette di dichiarare le importazioni P/Invoke con [LibraryImport("node")] e averle risolte contro il processo host a runtime.Marshalling delle stringhe UTF-8Uno dei punti più delicati è la conversione tra stringhe JavaScript (UTF-16 internamente in V8, UTF-8 via N-API) e stringhe .NET. La strategia ottimale prevede:Uso dello stack per stringhe piccole (≤512 byte) tramite stackallocUso di ArrayPool&lt;byte&gt; per stringhe più grandi, evitando allocazioni sull’heapprivate static string GetStringArg(nint env, nint info, int argIndex)
{
    // Recupera l'handle dell'argomento
    nint value = GetArgument(env, info, argIndex);
    
    // Prima chiamata: ottieni la dimensione necessaria
    nuint byteCount;
    napi_get_value_string_utf8(env, value, null, 0, out byteCount);
    
    // Allocazione efficiente in base alla dimensione
    if (byteCount &lt;= 512)
    {
        Span&lt;byte&gt; buffer = stackalloc byte[(int)byteCount + 1];
        napi_get_value_string_utf8(env, value, buffer, (nuint)buffer.Length, out _);
        return Encoding.UTF8.GetString(buffer[..^1]);
    }
    else
    {
        byte[] buffer = ArrayPool&lt;byte&gt;.Shared.Rent((int)byteCount + 1);
        try
        {
            napi_get_value_string_utf8(env, value, buffer, (nuint)buffer.Length, out _);
            return Encoding.UTF8.GetString(buffer, 0, (int)byteCount);
        }
        finally
        {
            ArrayPool&lt;byte&gt;.Shared.Return(buffer);
        }
    }
}Implementazione di una funzione reale: lettura dal RegistryL’esempio concreto mostrato dal team di Microsoft è un lettore del Windows Registry, che sostituisce il precedente addon C++:private static nint ReadStringValue(nint env, nint info)
{
    try
    {
        var keyPath = GetStringArg(env, info, 0);
        var valueName = GetStringArg(env, info, 1);
        
        using var key = Registry.CurrentUser.OpenSubKey(keyPath, writable: false);
        
        return key?.GetValue(valueName) is string value
            ? CreateString(env, value)
            : GetUndefined(env);
    }
    catch (Exception ex)
    {
        // CRITICO: le eccezioni non gestite in [UnmanagedCallersOnly] crashano il processo
        ThrowError(env, $"Registry read failed: {ex.Message}");
        return 0;
    }
}Attenzione: in un metodo [UnmanagedCallersOnly], le eccezioni non gestite provocano il crash dell’intero processo Node.js. Il pattern try/catch con ThrowError trasforma l’eccezione .NET in un errore JavaScript, mantenendo stabile il runtime.Integrazione con TypeScriptDopo dotnet publish, il file prodotto viene rinominato con estensione .node (convenzione Node.js) e caricato normalmente da TypeScript:interface RegistryAddon {
    readStringValue(keyPath: string, valueName: string): string | undefined;
}

const registry = require('./native/win32-x64/RegistryAddon.node') as RegistryAddon;

const sdkPath = registry.readStringValue(
    'SOFTWARE\\dotnet\\Setup\\InstalledVersions\\x64\\sdk',
    'InstallLocation'
);
console.log(`SDK installato in: ${sdkPath}`);Limiti e considerazioniQuesta tecnica ha un limite importante: Native AOT non supporta la cross-compilazione. Per ogni piattaforma target (Windows x64, Linux x64, macOS ARM64…) è necessario un ambiente di build separato. In pratica, questo si risolve con pipeline CI che eseguono la build su runner del sistema operativo corrispondente.Esiste anche un’alternativa di più alto livello, node-api-dotnet, che astrae molti dei dettagli mostrati qui e supporta scenari più complessi come l’esposizione di interi namespace .NET a JavaScript. L’approccio “thin wrapper” descritto in questo articolo è preferibile quando si vuole controllo totale e dipendenze minime.ConclusioniL’integrazione tra .NET Native AOT e N-API apre uno scenario interessante per i team che già lavorano con C# e devono interfacciarsi con l’ecosistema Node.js. Eliminare Python e node-gyp dal setup semplifica notevolmente l’ambiente di sviluppo e unifica le competenze necessarie intorno a un unico SDK.Il risultato è codice nativo con prestazioni paragonabili al C++, scritto con la produttività e la type safety di C# moderno, deployabile su Windows, Linux e macOS.Fonte: Writing Node.js addons with .NET Native AOT — Microsoft .NET Blog, Drew Noakes]]></description><link>https://forum.androidiani.net/topic/a0a8ba76-389e-4f9d-a652-0b5029500441/creare-addon-nativi-per-node.js-con-.net-native-aot-addio-a-python-e-node-gyp</link><guid isPermaLink="true">https://forum.androidiani.net/topic/a0a8ba76-389e-4f9d-a652-0b5029500441/creare-addon-nativi-per-node.js-con-.net-native-aot-addio-a-python-e-node-gyp</guid><dc:creator><![CDATA[blog@spcnet.it]]></dc:creator><pubDate>Wed, 22 Apr 2026 09:19:56 GMT</pubDate></item><item><title><![CDATA[Rust 1.95.0: cfg_select!, if-let guard nei match e nuove API per Vec e atomici]]></title><description><![CDATA[Il 16 aprile 2026 è uscita Rust 1.95.0, una release che porta novità significative al linguaggio e alla sua libreria standard. Questa versione si segnala in particolare per l’introduzione della macro cfg_select!, il supporto agli if-let guard nei blocchi match, e una serie di nuove API per la gestione della memoria e degli atomici.Vediamo nel dettaglio cosa cambia e come queste novità influenzano il codice quotidiano dei Rustaceans.cfg_select!: condizionali di compilazione senza dipendenze esterneLa macro cfg_select! introduce un modo più espressivo per scrivere codice condizionale basato sulla configurazione di compilazione. Si comporta come un match valutato a compile-time sulle condizioni cfg, rimpiazzando di fatto il crate esterno cfg-if che molti progetti Rust usano da anni.Prima di Rust 1.95, per scrivere codice dipendente dalla piattaforma si usava tipicamente:// Prima: con cfg-if (dipendenza esterna nel Cargo.toml) cfg_if::cfg_if! {     if #[cfg(target_os = "linux")] {         fn get_system_info() -&gt; String {             linux_system_info()         }     } else if #[cfg(target_os = "macos")] {         fn get_system_info() -&gt; String {             macos_system_info()         }     } else {         fn get_system_info() -&gt; String {             String::from("unknown")         }     } }Con cfg_select!, la stessa logica si esprime ora senza aggiungere dipendenze al progetto:// Ora: built-in nella libreria standard fn get_system_info() -&gt; String {     cfg_select! {         target_os = "linux" =&gt; { linux_system_info() }         target_os = "macos" =&gt; { macos_system_info() }         _ =&gt; { String::from("unknown") }     } }La sintassi è più pulita e il fatto di essere nella libreria standard elimina la necessità di dichiarare cfg-if nel Cargo.toml. Particolarmente utile per chi sviluppa librerie cross-platform o crate che devono supportare più sistemi operativi e architetture CPU.if-let guard nei match: pattern matching più espressivoRust 1.95 stabilizza gli if-let guard all’interno delle espressioni match, costruendo sulle let chain introdotte in Rust 1.88. Un guard in un match è la condizione if che può seguire un pattern. Finora, questa condizione doveva essere un’espressione booleana semplice. Ora si può usare if let per abbinare pattern aggiuntivi direttamente nella guardia:fn process(value: Option&lt;Result&lt;i32, String&gt;&gt;) {     match value {         Some(x) if let Ok(y) = x =&gt; {             println!("Valore ottenuto: {}", y);         }         Some(Err(ref e)) =&gt; {             println!("Errore: {}", e);         }         None =&gt; {             println!("Nessun valore");         }     } }Questo permette di scrivere logica di pattern matching più complessa senza ricorrere a blocchi match annidati. Un caso d’uso pratico è la validazione combinata di metodo HTTP e corpo della richiesta:fn handle_request(req: &amp;Request) -&gt; Response {     match req.method() {         Method::POST if let Ok(body) = serde_json::from_str::&lt;Payload&gt;(req.body()) =&gt; {             process_payload(body)         }         Method::POST =&gt; {             Response::bad_request("Payload JSON non valido")         }         _ =&gt; {             Response::method_not_allowed()         }     } }Nota importante sull’esaustività: il compilatore non tiene conto dei pattern negli if-let guard per il controllo di esaustività (exhaustiveness checking). Questo significa che il compilatore non avvertirà se un pattern nell’if-let guard è irraggiungibile. Occorre quindi prestare attenzione quando si usano questi costrutti in match che devono essere esaustivi per correttezza.Nuove API per Vec, VecDeque e atomicipush_mut e push_back_mut: riferimenti mutabili post-inserimentoUna delle aggiunte più pratiche riguarda i metodi push_mut e varianti per Vec e VecDeque. Questi metodi inseriscono un elemento e restituiscono immediatamente un riferimento mutabile all’elemento appena inserito, eliminando il doppio accesso che prima era necessario:// Prima: due operazioni separate let mut v: Vec&lt;String&gt; = Vec::new(); v.push(String::new()); let last = v.last_mut().unwrap(); // secondo accesso necessario last.push_str("hello");  // Ora con push_mut: un unico accesso, più efficiente let mut v: Vec&lt;String&gt; = Vec::new(); let elem = v.push_mut(String::new()); elem.push_str("hello"); // riferimento diretto all'elemento appena inseritoMetodi analoghi (push_back_mut, push_front_mut) sono disponibili anche su VecDeque, utile per code e buffer circolari.update e try_update sugli atomiciI tipi atomici (AtomicUsize, AtomicBool, AtomicI32, ecc.) guadagnano i metodi update e try_update per semplificare i pattern read-modify-write senza dover scrivere manualmente il loop CAS (Compare-And-Swap):use std::sync::atomic::{AtomicUsize, Ordering};  let counter = AtomicUsize::new(0);  // Incrementa atomicamente, restituisce il vecchio valore let old = counter.update(Ordering::SeqCst, |x| x + 1); println!("Valore precedente: {}", old);  // try_update: permette di fallire condizionalmente // (ritorna Err se la chiusura restituisce None) let result = counter.try_update(Ordering::SeqCst, |x| {     if x &lt; 100 { Some(x + 1) } else { None } });  match result {     Ok(old_val) =&gt; println!("Aggiornato da {}", old_val),     Err(_) =&gt; println!("Limite raggiunto, nessun aggiornamento"), }Questi metodi gestiscono internamente il retry loop in caso di contesa tra thread, rendendo il codice più leggibile e meno soggetto a errori.Stabilizzazioni in const contextRust 1.95 estende il supporto ai const context per alcune API già stabili, consentendo un uso più ampio della valutazione a compile-time:fmt::from_fn ora utilizzabile in contesti constMetodi di ControlFlow ora const-stabiliNuovi metodi unsafe per puntatori: as_ref_unchecked e as_mut_uncheckedLayout::dangling_ptr per manipolazione avanzata della memoria in allocatori customBreaking change: JSON target spec non più supportata su stableRust 1.95 rimuove il supporto alle specifiche di target in formato JSON sul canale stable. Questa funzionalità era già effettivamente limitata al canale nightly (costruire core richiedeva già nightly), quindi l’impatto pratico è minimo per la maggior parte dei progetti. Chi usa target custom non standard dovrà assicurarsi di usare il canale nightly o di migrare a definizioni di target ufficialmente supportate.Come aggiornarePer aggiornare Rust all’ultima versione stabile, basta eseguire:rustup update stablePer verificare la versione installata:rustc --version # rustc 1.95.0 (xxxxxxxx 2026-04-16)ConclusioniRust 1.95.0 è una release solida che porta miglioramenti trasversali all’ergonomia del linguaggio. cfg_select! riduce la dipendenza da crate esterni per il codice condizionale, gli if-let guard aumentano l’espressività del pattern matching, e le nuove API per Vec e atomici semplificano pattern comuni nella gestione dello stato condiviso in contesti concorrenti.Nel complesso, questa release conferma la direzione del progetto Rust: migliorare l’ergonomia senza compromettere la sicurezza, incorporando nella libreria standard soluzioni che prima richiedevano crate esterni.Fonte: Announcing Rust 1.95.0 — The Rust Programming Language Blog]]></description><link>https://forum.androidiani.net/topic/0053a857-f38f-471f-bb65-f87de462fc3b/rust-1.95.0-cfg_select-if-let-guard-nei-match-e-nuove-api-per-vec-e-atomici</link><guid isPermaLink="true">https://forum.androidiani.net/topic/0053a857-f38f-471f-bb65-f87de462fc3b/rust-1.95.0-cfg_select-if-let-guard-nei-match-e-nuove-api-per-vec-e-atomici</guid><dc:creator><![CDATA[blog@spcnet.it]]></dc:creator><pubDate>Mon, 20 Apr 2026 11:58:16 GMT</pubDate></item></channel></rss>