Archivi tag: C

IMG_4582-1.png

C reflection ?

Da qualche tempo ho ripreso a programmare in puro C per dei miei progetti personali, e quando dico puro intendo utilizzando essenzialmente la libreria standard come unico ausilio e primitive di sistema ove possibile.Non amo appoggiarmi ad API terze parti, per due (credo) ottime ragioni: esiste un tempo di apprendimento della loro logica non sempre nullo, e quasi sempre si adotta solo una minima percentuale delle funzioni date: che spreco di bit!
Poi una ragione diciamo di orgoglio, è che mi piace conoscere e trovare tecniche e soluzioni a problemi per mio conto, quasi sempre cercando (è un istinto della mia generazione) di sprecare pochi bit e pochi cicli CPU! Che noia, eh?!
Certo dopo qualche anno di C++, Java e Objective-C (in ordine cronologico), la mancanza di alcuni costrutti o strumenti si è fatta sentire: ci si vizia facilmente! Però si sopravvive.
In particolare un mio programma, instaurando un dialogo simbolico con un suo client aveva la necessità di cercare nelle sue strutture di memoria mediate il simbolo rappresentante un attributo di struttura: un classico esempio di reflection.
Abituato nell’ultimo periodo al paradigma Key-Value-Coding, la sua assenza mi pesava. Un approccio classico switch-case comportava la codifica numerica dei simboli (siamo in C, non PHP!). Una sequenza di if-else-if con strcmp “a manciate” non mi sembrava elegante: quindi?
Quindi perché non trovare un modo di implementare un abbozzo di reflection istruendo il programma sulla sua struttura?
Occorreva una tabella di meta-dati: nome del membro della struttura, spiazzamento da base di memoria della struttura e una funzione associata che applicasse un qualche algoritmo (a me serviva una comparazione tra i valori della struttura e un parametro di riferimento) tenendo conto del tipo dato.
Soluzione? La vecchia e cara aritmetica degli indirizzi!
Certo, come tutti sappiamo le cose così si complicano e diventano maledettamente illeggibili, ma per fortuna l’ambiente di sviluppo in Linux (a già dimenticavo! stavo implementando per questo specifico sistema) mi è venuto incontro con una macro di pre-processing che ha semplificato e reso leggibile il tutto.
Si tratta di “offsetof” definita in stddef.h e usata in ambito sviluppo kernel (con alcune varianti possibili): ovviamente troverete il file in /usr/src/linux-header-$(uname -r)/include/linux che quindi divrete avere.
Dunque con una struttura formata da 

  • const char *
  • size_t
  • int (*)(void *, void *)

ho potuto così creare una lookup table con cui ispezionare in riflessione la memoria del programma (relativamente a una certa struttura dati).

Ovviamente il size_t popolato dalla macro “offsetof” , mente la funzione nel mio caso doveva essere capace di comparare due argomenti del tipo pari all’attributo considerato, di cui appunto un argomento sarebbe stato proprio l’attributo.
Per accedere al dato nella struttura una volta riconosciuto il nome, la funzione di lookup non doveva fare altro che convertire in char * l’indirizzo base della struttura stessa e sommarci l’offset dato nella riga della lookup table che aveva consentito il riconoscimento, ottenendo un puntatore che convertito in void * e passato assieme al parametro di riferimento alla funzione associata che avrebbe provveduto (conoscendo il tipi originale) ad eseguire quanto voluto in modo coerente.

Basta ?

Forse no in termini assoluti, ma per la mia implementazione avere una struttura con 2 attributi o 50 è stato solo un gioco di riempimento della (o delle) lookup table, dopodiché lo stesso codice ha fatto quanto previsto in tutte le circostanze e in tutti gli aggiornamenti della struttura dati (e lookup table).

Alla prossima!

osx-vb-cpuid

OSX+VirtualBox+cpuid

Il mondo degli smanettoni è a volte omissivo, a volte ignorante. L’omissivo lo ammetto quando serve ad impedire a giovani sprovveduti di replicare tecniche pericolose o illegali; l’ignoranza è altra cosa. Ma nel chiacchiericcio internet, persa la fonte originale (forse solo omissiva), dopo molti “copia e incolla” molti post diventano un crogiolo di ignoranza.

Non so se questo sia il caso, ma non si trova molto in giro che spieghi le relazioni profonde tra le cose oggetto di questo post.

Cpuid è una istruzione assembly Intel che consente di determinare tipo e caratteristiche della cpu (ovviamente solo per architetture Intel/AMD).

L’insieme di informazioni risultanti è usato da sistemi operativi e software applicativi per determinare certi comportamenti.

Nel caso di  Oracle VirtualBox vengono utilizzate per determinare se il sistema host può eseguire il codice del sistema guest; ma VirtualBox usa una versione “edulcorata” di queste informazioni anche per mostrare al guest la CPU virtuale che intende fornire. Tipicamente fa questo clonando le informazioni cpuid della CPU reale modificando alcune caratteristiche (per ragioni di isolamento e protezione).

VirtualBox fornisce uno strumento per interrogare la CPU host rispetto al cpuid:

VBoxManage list hostcpuids

Consente anche un certo grado di intervento nell’immagine virtuale di queste informazioni che fornirà al sistema guest:

VBoxManage modifyvm --cpuidset

ma attenzione: potranno essere arbitrariamente alterate da VirtualBox per le ragioni di isolamento e protezione di cui sopra.

Come si relaziona tutto questo con OSX?

Parliamoci chiaro: su internet la maggior parte dei post che trattano questi argomenti lo fanno spiegando di installazioni OSX su hardware e OS “non Apple“: questo non è consentito dalle licenze d’uso.

Nessuno tratta argomenti più “Apple” come la sperimentazione di nuove versioni di OSX prima in virtuale (tipico approccio conservativo per chi personalizza pesantemente il sistema e deve sapere se tutto funzionerà correttamente, se software particolari e magari costosi funzioneranno ancora, ecc). Nessuno parla mai dello sviluppo “legacy”, quindi della necessità di avere una vecchia versione di OSX su cui sperimentare il software.

VirtualBox per OSX è lo strumento ideale per tutte queste cose.

Grazie alla manipolazione delle informazioni cpuid Potremo testare anche per hardware differente (sempre Apple, ma meno recente).

Ma OSX non ha uno strumento nativo per leggere il cpuid; quindi se non vogliamo installare VirtualBox su tutte le macchine da cui estrarre le informazioni cpuid  ci serve uno strumento alternativo.

È quello che propongo con questa mia semplice implementazione in C:

http://www.github.com/andrea-tassotti/cpuid

Il codice deriva da un sorgente open source di Apple (con licenza non GPL), e produce un output come quello di VBoxManage.

Il vantaggio di questo codice è che potrà essere eseguito all’interno del sistema guest per verificare che le informazioni impostate in configurazione della VM siano come previste (salvo modifiche applicate da VirtualBox).

Spero possa esserVi di qualche aiuto per comprendere certi meccanismi.

Alla prossima

osxbeep

Beep OS X, Beep!

Nell’implementazione dello strato BSD, OSX omette alcuni comandi; poco male se una alternativa è data da un comando nativo: verosimilmente l’astrazione BSD non era in grado di realizzare a pieno il compito. Ma questo non é evidentemente l’unico motivo.

Tra i vari “ports” BSD, Apple ne seleziona solo alcuni, mantenendoli spesso ad una versione “vecchia” (vedi il caso di bash, ancora rimasta alla 3).

Non dovrebbe dunque sorprendere l’assenza del port del comando beep, sebbene sia difficilmente spiegabile in termini tecnologici; al piú si spiega in termini di conformità alle metafore della interfaccia che prevedono altro per la segnalazione di eventi ad utente.

L’ironia del caso vuole che mentre il mondo Linux evolve la sua implementazione del comando beep, anche il port per FreeBSD è stato rimosso in quanto obsoleto, alla buona faccia di chi voglia ancora utilizzarlo.
Ovviamente il nostro interesse per il comando beep nel mondo OS X è indotto dalle cose espresse nei nostri precedenti articoli, ma andiamo per gradi.
Ricercando nella documentazione di sviluppo si trova la disponibilità della funzione beep() nella libreria ncurses (https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/beep.3x.html): questa peró esegue il suono di avviso configurato negli effetti sonori nelle preferenze di sistema.
Quindi, almeno per conformità alle metafore dell’interfaccia, il comando beep poteva essere implementato semplicemente utilizzando questa funzione di ncurses.

Ricercando in Internet (come è nostro solito) una soluzione per implementare un beep su OS X troviamo tante risposte ovvie, ma non quella che cercavamo (ovvio anche questo!)

E’ ovvio che un comando echo (o print) in shell riproduca con un suono il carattere audible alert (\a=ASCII 0x7, carattere di controllo
che deve i suoi natali alla Teletype Model 33 ASR):

echo -e "\a"

ma é anche ovvio che si comporti come prevede l’implementazione della libreria ncurses, come per l’equivalente:

tput bel

con cui si attiva la capability del terminale (che dipendono dalla solita libreria)

Ovvio (benchè meno diretto) la possibilitá di eseguire un beep come istruzione AppleScript:

osascript -e beep

e non ci si può stupire se anche questo metodo (piú che mai OS X) esegue Il suono di sistema previsto per gli avvisi.

Il suggerimento piú esilarante è certamente il seguente:

say beep

benchè abbia un suo fascino.
Dunque è giunto il momento di trovare una risposta in stile Nerdammer e dotare il nostro OS X del comando beep.
Volevamo scegliere come modello la piú evoluta implementazione Linux (di Johnathan Nightingale) invece di quella del port FreeBSD:
questioni pratiche e di tempo ci impongono al momento di implementare la versione FreeBSD: ritorneremo sulla implementazione per evolverla accessivamente.

Questa scelta ci consentirà comunque di utilizzare le nostre “beepsongs” come prodotte dal software descritto nel
precedente articolo (ponendo in modo FreeBSD l’output dello script). Alla fine in realtà è questo che cercavamo!

Per realizzare il nostro progetto ci avvaliamo del framework Core Audio, ed in particolare utilizziamo una Audio Unit di tipo output con definita una funzione callback per il rendering del buffer audio, il che ci consentirà di definire algoritmicamente (dunque dinamicamente) la forma d’onda emessa.

Vogliamo con questo simulare al meglio il circuito analogico del beeper delle schede madri di pc e server, evitando i limiti e la complessità che altri metodi imporrebbero volendo ottenere campo di frequenze e durata di emissione molto ampi.

Come al solito la nostra implementazione é una guida: ci si perdoni quindi l’assenza di ricerca di ottimizzazioni nelle prestazioni (ad esempio l’algoritmo di generazione dell’onda sinusoidale non é il piú efficiente in assoluto).

Potete scaricare il codice sorgente da Git Hub e compilarlo sul vostro OS X come indicato nella documentazione.

Ancora una volta buon ascolto!

IMG_3049.PNG

Estendere le capacitˆà di stampa di Cocoa

Avete realizzato l’interfaccia per cdlabelgen come descritto nel precedente post?

Beh, io si e ho affrontato anche il problema della stampa: voi?

La stampa in programmi Cocoa deriva dall’essenziale derivazione del motore grafico Quartz dal PDF. Quindi in Cocoa la stampa nasce dalla costruzione di un suo oggetto NSView da cui discendano come contenuto tutte le componenti grafiche necessarie a strutturare il layout finale.

Quello che otteniamo è dunque una relazione 1:1 tra widget Cocoa, testo e immagini e le componenti PDF che porteremo alla stampa.

Ma con cdlabelgen abbiamo a che fare con postscript: questo è ciò che viene generato dallo script. Che PDF e postscript siano parenti non aiuta affatto!

Cercando in Internet non ho trovato soluzioni, nemmeno lontanamente. Che la cosa non fosse mai stata affrontata o fosse stata risolta con librerie proprietarie dai software di grafica con tanto di blasone mi sembrava alquanto strana.

Poi (la disperazione a volte aiuta!) mi sono ricordato che nella cartella esempi di XCode qualcosa riguardo la stampa era presente: ho cominciato a cercare e studiare, tornando sull’indispensabile (e preziosa) documentazione ADC.

Ed ecco a voi la soluzione (Apple, non mia: io ho solo ritrovato e ora pubblicizzato tale soluzione).

Dicevamo che i frameworks che compongono l’universo Cocoa (in particolare AppKit) supportano una limitata visione del processo di stampa, segnatamente una versione NSView-centrica gestita attraverso le seguenti astrazioni:

  • NSPageLayout
  • NSPrintInfo
  • NSPrintOperation
  • NSPrintPanel
  • NSPrinter

Un supporto completo alla stampa deriva (da indicazione esplicita in documentazione) dall’utilizzo diretto del framework Core Printing, una API in C di cui AppKit crea una interfaccia limitata.

La soluzione da noi cercata per stampare dati postscript (file, in particolare) è la funzione PMPrinterPrintWithFile presente in questo framework; il suo prototipo è:

OSStatus PMPrinterPrintWithFile (

 PMPrinter printer,

 PMPrintSettings settings,

 PMPageFormat format,

 CFStringRef mimeType,

 CFURLRef fileURL

);

Come possiamo vedere mediante il parametro fileURL si fornisce un percorso al file da stampare, file di cui mediante parametro mimeType si indica anche il tipo. La specifica di tipo è importante in quanto deve coincidere con uno dei tipi supportati dal framework; i tipi supportati (ricavati dalla funzione per la validazione del tipo passato) sono:

  •     “application/octet-stream”
  •     “application/pc-eps”
  •     “application/pdf”
  •     “application/pictwps”
  •     “application/postscript”
  •     “application/vnd.apple-postscript”
  •     “application/vnd.cups-banner”
  •     “application/vnd.cups-command”
  •     “application/vnd.cups-postscript”
  •     “application/vnd.cups-raster”
  •     “application/vnd.cups-raw”
  •     “application/vnd.hp-hpgl”
  •     “application/x-cshell”
  •     “application/x-csource”
  •     “application/x-perl”
  •     “application/x-shell”
  •     “application/xhtml+xml”
  •     “image/fuji-raw”
  •     “image/gif”
  •     “image/imageio”
  •     “image/jp2”
  •     “image/jpeg”
  •     “image/minolta-raw”
  •     “image/openexr”
  •     “image/pict”
  •     “image/png”
  •     “image/rad”
  •     “image/tiff”
  •     “image/x-alias”
  •     “image/x-bitmap”
  •     “image/x-bmp”
  •     “image/x-ico”
  •     “image/x-icon”
  •     “image/x-photocd”
  •     “image/x-portable-anymap”
  •     “image/x-portable-bitmap”
  •     “image/x-portable-graymap”
  •     “image/x-portable-pixmap”
  •     “image/x-psd”
  •     “image/x-qtif”
  •     “image/x-sgi-rgb”
  •     “image/x-sun-raster”
  •     “image/x-tga”
  •     “image/x-xbitmap”
  •     “image/x-xpixmap”
  •     “text/html”
  •     “text/plain”
  •     “text/rtf”

Non male, vero?

È ovvio che per invocare questa funzione occorre completarne la lista argomenti: stampante, formato e settaggio per il processo di stampa.
Questi ultimi due parametri li ricaviamo fortunatamente direttamente in AppKit, in particolare da una istanza condivisa di NSPrintInfo 

 [NSPrintInfo sharedPrintInfo]

dopo averla popolata utilizzando NSPrintPanel e NSPageLayout (le componenti Cocoa che realizzano le finestre di dialogo utente per le rispettive finalitˆà utilizzando una istanza di NSPrintInfo). Per Il parametro stampante invocheremo PMSessionGetCurrentPrinter() passando la sessione ottenuta sempre da NSPrintInfo dopo averle collegato settaggio e formato mediante PMSessionDefaultPrintSettings() e PMSessionValidatePageFormat() (funzioni di Core Printing).

Mettendo assieme il tutto avrete la vostra stampa di file postscript.
Questo un rapido quadro della soluzione: per i dettagli c’e’ la documentazione: replicarla qui mi sembra troppo!

Alla prossima!