Attualmente sto giocando con l'idea di progettare una C API un po 'sofisticata. Ho esaminato le API esistenti e ho trovato un approccio interessante che ruotava attorno a% opacostruct
s. Nello specifico, ho visto un'API che ha il seguente aspetto (in un file api.h
):
typedef struct Object Object;
typedef struct API API;
typedef void (*object_manipulate)(Object* object,
int value);
void api_create(API** api,
Object* object,
object_manipulate manipulate);
void api_manipulate(API* api, int value);
Questo sembra un approccio starightforward, la struttura API
memorizza il file
puntatore di funzione e Object*
e invia chiamate.
Ciò che mi ha sorpreso è il fatto che è possibile avere più implementazioni in diverse unità di compilazione che definiscono definizioni diverse di il codice%. Ad esempio è possibile aggiungere un file "one.c" contenente l'implementazione one dell'API:
#include "api.h"
struct Object
{
int x;
};
static void object_manipulate_one(Object* object,
int value)
{
//...
}
void create_api_one(API** api, int x)
{
Object* object = malloc(sizeof(Object));
object->x = x;
api_create(api, object, object_manipulate_one);
}
Un'intestazione corrispondente può rendere accessibile la funzione struct Object
.
Tuttavia, è possibile creare un file "two.c" contenente una diversa create_api_one
definizione:
#include "api.h"
struct Object
{
char y;
};
// similar functions as above
Questo solleva un paio di domande:
- I diversi file vengono compilati e possono essere collegati in un unico file eseguibile.
Tuttavia, lo spostamento di tutto in un file "* .c" aumenta
un errore
struct Object
. ho pensato tutti i simboli sarebbero esportati negli oggetti, mantenendo tenere presente che le definizioni sono non statiche. Perché il codice viene compilato? - La tecnica passa da una parola chiave (o è un modello di progettazione)?
- È considerato una buona pratica utilizzare questo approccio o è considerato hacky?