initial commit
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Frameworks y librerías del ecosistema C/C++
|
||||
|
||||
## Qt (C++, no C)
|
||||
|
||||
- Framework multiplataforma en **C++**: interfaces gráficas, red, hilos,
|
||||
bases de datos, impresión, multimedia. Funciona en Windows, Linux, macOS,
|
||||
Android, iOS y sistemas embebidos.
|
||||
- Lo usan KDE, OBS Studio, Telegram Desktop, VirtualBox y muchos sistemas de
|
||||
coche y de punto de venta.
|
||||
- **Señales y slots**: un objeto emite un evento y otros lo reciben. Para
|
||||
implementarlo, Qt tiene un precompilador propio (`moc`) que genera código
|
||||
C++ adicional antes de compilar.
|
||||
- **QML**: lenguaje declarativo, parecido a JS, para las interfaces modernas.
|
||||
- **Licencia**: LGPLv3 o comercial (algunos módulos solo GPL o comercial). Con
|
||||
LGPL hay que permitir que el usuario sustituya las librerías de Qt, y por
|
||||
eso las aplicaciones Qt se distribuyen con sus DLL al lado.
|
||||
- **Relación con este proyecto**: una aplicación Qt imprime con `QPrinter`, que
|
||||
pasa por el driver del fabricante y el spooler. Para ESC/POS en crudo
|
||||
(cajón, corte, estado) necesitaría una librería como esta.
|
||||
|
||||
## Por qué en C casi no hay "frameworks"
|
||||
|
||||
- La librería estándar de C es mínima: no trae red, ni contenedores, ni JSON,
|
||||
ni HTTP. Los hilos (`threads.h`) llegaron en C11 y son opcionales.
|
||||
- No hay gestor de paquetes oficial ni genéricos.
|
||||
- Cultura resultante: **librerías pequeñas que se combinan**. Muchas son de
|
||||
"una sola cabecera" o de un solo `.c`, para poder copiarlas en el proyecto
|
||||
sin más.
|
||||
|
||||
**En Go**: la librería estándar ya trae `net/http`, `encoding/json`, `sync`,
|
||||
etc., más `go get`.
|
||||
|
||||
## Librerías C relevantes
|
||||
|
||||
| Librería | Qué es | Relación |
|
||||
|---|---|---|
|
||||
| **GTK** + **GLib/GObject** | Interfaz gráfica de GNOME y GIMP. GObject implementa orientación a objetos a mano sobre C | Ejemplo de cómo simular clases e interfaces en C |
|
||||
| **SDL** | Ventanas, gráficos, audio y entrada; multiplataforma, incluido Android | Juegos y multimedia |
|
||||
| **LVGL** | Interfaces gráficas para microcontroladores con pantalla | Terminales de punto de venta embebidos |
|
||||
| **libuv** | Bucle de eventos multiplataforma | Es el motor de Node.js: lo que hay debajo de JS |
|
||||
| **libcurl** | Cliente HTTP y muchos protocolos más | |
|
||||
| **SQLite** | Base de datos completa en un solo `.c` | Código C de referencia, muy bien probado |
|
||||
| **libusb** | Acceso a USB desde modo usuario | Candidata para las fases 5 y 9 |
|
||||
| **zlib**, **OpenSSL** | Compresión y criptografía | |
|
||||
| **Unity**, **cmocka** | Frameworks de tests para C | Para probar la librería |
|
||||
| **stb** | Colección de librerías de una sola cabecera (por ejemplo, `stb_image` para cargar PNG o JPEG) | Posible ayuda en la fase 7 (imágenes) |
|
||||
|
||||
## Interfaces en C
|
||||
|
||||
Una `interface` de Go se implementa en C como un `struct` de **punteros a
|
||||
función**. Así funcionan GObject, los drivers de Linux y, en la fase 4, la
|
||||
abstracción de transportes de la librería (LAN, USB) detrás de una misma API.
|
||||
|
||||
### Piezas
|
||||
|
||||
- **Puntero a función**: las funciones también están en memoria (en la
|
||||
sección `.text`; la dirección que muestra `nm` junto a cada `T`). Un
|
||||
puntero a función guarda esa dirección y permite llamarla.
|
||||
Sintaxis: `double (*area)(const void *self);`.
|
||||
- **`void *`**: un puntero "a cualquier cosa", sin tipo. Hace el papel del
|
||||
receptor del método. C no tiene métodos: el objeto se pasa explícitamente.
|
||||
Go hace lo mismo por dentro: `c.Area()` se compila como `Area(c)`.
|
||||
- **vtable**: un `struct` con los punteros a función de un tipo concreto. Se
|
||||
define una vez por tipo y la comparten todas sus instancias.
|
||||
- **Valor de la "interfaz"**: dos punteros, `{vtable, datos}`.
|
||||
|
||||
### Cómo es una interfaz de Go por dentro
|
||||
|
||||
En el runtime de Go, una interfaz con métodos es exactamente eso:
|
||||
|
||||
```go
|
||||
type iface struct {
|
||||
tab *itab // tipo concreto + punteros a sus métodos
|
||||
data unsafe.Pointer // el valor concreto
|
||||
}
|
||||
```
|
||||
|
||||
Por eso una interfaz ocupa 16 bytes en 64 bits. Y por eso existe la trampa
|
||||
del `nil`:
|
||||
|
||||
```go
|
||||
var p *MyError = nil
|
||||
var err error = p
|
||||
err != nil // true: tab apunta al tipo *MyError, aunque data sea nil
|
||||
```
|
||||
|
||||
Una interfaz solo es `nil` si **los dos** campos son `nil`.
|
||||
|
||||
### Qué hace Go por ti y qué haces tú en C
|
||||
|
||||
| Go | C |
|
||||
|---|---|
|
||||
| Comprueba en compilación que el tipo implementa la interfaz | Nadie lo comprueba: rellenas la vtable a mano |
|
||||
| Construye el `itab` automáticamente | Declaras la vtable como `static const` |
|
||||
| El receptor tiene su tipo | `void *`: si pasas el objeto equivocado, comportamiento indefinido |
|
||||
| Un método que falta no compila | Un puntero a `NULL` en la vtable provoca un fallo al llamarlo |
|
||||
|
||||
### Ejemplo real: los drivers de Linux
|
||||
|
||||
Cada driver rellena un `struct file_operations` con punteros a sus funciones
|
||||
`open`, `read`, `write`... Cuando un programa hace `write()` sobre
|
||||
`/dev/usb/lp0`, el núcleo llama a `usblp_write` a través de ese puntero. Es
|
||||
el `io.Writer` del núcleo de Linux.
|
||||
Reference in New Issue
Block a user