2010-05-24 16 views
6

Devo fornire una libreria statica C al client e devo essere in grado di rendere non disponibile una definizione di struct. Oltre a questo ho bisogno di essere in grado di eseguire il codice prima dell'inizializzazione della libreria principale utilizzando una variabile globale.Nascondere la definizione di struct nella libreria statica

Ecco il mio codice:

private.h 


#ifndef PRIVATE_H 
#define PRIVATE_H 

typedef struct TEST test; 

#endif 


private.c (this should end up in a static library) 

#include "private.h" 
#include <stdio.h> 

struct TEST 
{ 
TEST() 
{ 
    printf("Execute before main and have to be unavailable to the user.\n"); 
} 

int a; // Can be modified by the user 
int b; // Can be modified by the user 
int c; // Can be modified by the user 

} TEST; 


main.c 

test t; 

int main(void) 
{ 
t.a = 0; 
t.b = 0; 
t.c = 0; 

return 0; 
} 

Ovviamente questo codice non funziona ... ma mostrare ciò che ho bisogno di fare ... Qualcuno sa come fare questo lavoro? Io google un po 'ma non riesco a trovare una risposta, qualsiasi aiuto sarebbe molto apprezzato.

TIA!

risposta

7

Se stai usando gcc è possibile utilizzare l'attributo costruttore,

void runs_before_main(void) __attribute__((constructor)) 
{ 
    ... 
} 

Dalla documentazione gcc

L'attributo costruttore fa sì che la funzione da chiamare automaticamente Be- esecuzione ribalta entra principale(). Allo stesso modo, l'attributo di distruttore causa la chiamata automatica della funzione dopo che main() ha completato o è stato chiamato exit(). Le funzioni con questi attributi sono utili per inizializzare i dati che saranno utilizzati implicitamente durante l'esecuzione del programma .

Si possono prevedere una priorità opzionale intero per controllare l'ordine in cui vengono eseguiti costruttore e distruttore funzioni . Un costruttore con un numero di priorità minore viene eseguito prima di un costruttore con un numero maggiore di priorità ; la relazione opposta vale per i distruttori. Quindi, se hai un costruttore che alloca una risorsa e un distruttore che rilascia la stessa risorsa, entrambe le funzioni in genere hanno la stessa priorità . Le priorità per costruttore e distruttore funzioni sono le stesse di quelle specificate per namespace-ambito C++ oggetti

Se si desidera nascondere una struttura da parte degli utenti, dichiarare la struct in un colpo di testa, ma definirlo nel c file, passando intorno ai puntatori. Come esempio:

// foo.h 
typedef struct private_foo foo; 
foo * create_foo(void); 
void free_foo(foo * f); 

// foo.c 
struct private_foo { 
    int i; 
} 
foo * create_foo(void){ 
    foo * f = malloc(sizeof(*foo)); 
    if (f) f->i = 1; 
    return f; 
} 
... 

foo->i non può quindi accessibili all'esterno foo.c.

3

Se si desidera che il codice client sia in grado di utilizzare "t.a = ...", non è possibile nascondere la definizione della struttura. Quello che vuoi è chiamato un tipo opaco, che sarà simile a questo:

 
public.h: 
struct foo; 
set_a(struct foo *, int); 
struct foo * new_foo(void); 

main.c: 
#include <public.h> 
int main(void) 
{ 
    struct foo *k; 
    k = new_foo(); 
    set_a(k, 5); 
} 

definizione La struttura è disponibile solo per la biblioteca. Se non si rende disponibile il codice sorgente della libreria, è possibile nasconderlo completamente dagli utenti della libreria.

2

Non esiste un modo portatile in C per garantire che il codice venga eseguito prima dello main().Quello che vorrei fare è semplicemente mantenere un flag initialised nella libreria, impostare su false e quindi rifiutare di fare qualsiasi cosa fino a quando non viene chiamata la funzione init.

Come in:

static int initialised = 0; 

int init (void) { 
    // do something. 
    initialised = 1; 
    return ERR_OK; 
} 

int all_other_functions (void) { 
    if (!init) 
     return ERR_NOT_INITED; 

    // do something. 
    return ERR_OK; 
} 
+0

Utilizzando un tipo incompleto per la maniglia consente al compilatore di rilevare gli errori di tipo, ed evita colata nelle funzioni di attuazione. –

+0

Il compilatore può _still_ rilevare errori di tipo poiché il codice della libreria funziona con la variabile correttamente digitata. Oppure, se in realtà volevi dire che il tipo sbagliato è stato assegnato alle tue funzioni, questo è un errore dell'utente e meritano tutte le difficoltà che porterà :-) Come ho detto, è un modo _one_ di farlo, non l'unico modo. – paxdiablo

+0

Perché mai usare l'uso void * e perdere tutti i controlli di tipo? typedef struct MyHiddenStruct MyHandle; MyHandle * allocHandle(); –

Problemi correlati