2012-08-15 28 views
6

Ho una libreria C statica che posso creare con diverse opzioni di compilazione (ad es. _BUILD_SMALL, _BUILD_FAST). Ha una funzioneCome alias delle funzioni della libreria C?

void Foo(void); 

Vorrei utilizzare una singola istanza di uno strumento di benchmarking al benchmark le versioni "veloci" della biblioteca "piccolo" e. Non voglio usare .dlls.

Come posso collegarmi alle librerie "piccola" e "veloce" e fare l'alias dei nomi delle funzioni in modo da poter chiamare la versione piccola e la versione veloce. L'ideale sarebbe simile:

void benchmark(void) 
{ 
    FAST_Foo(); 

    SMALL_Foo(); 
} 

Maggiori informazioni:

La biblioteca può essere costruito con diverse ottimizzazioni opzioni -os contro -O3. Inoltre, gli algoritmi variano leggermente (vale a dire valori memorizzati nella cache e valori di ricerca sempre). Voglio confrontare le dimensioni e i compromessi di velocità delle diverse versioni. Mi piacerebbe che i test unitari e il benchmarking fossero eseguiti su entrambe le versioni della libreria nel modo più semplice possibile.

+2

Questa domanda è molto poco chiara. – Falmarri

+0

Perché non creare semplicemente più versioni con varie opzioni attivate/disattivate e confrontate ciascuna di esse? –

+0

Non è possibile combinare entrambe le funzioni in un singolo collegamento se sono denominate uguali (e non sono statiche). – mah

risposta

3

Questa è solo una variante del metodo, come dato da @ Michał Górny (ho esaurito commento spazio lì) ...

è possibile creare un file del seguente modulo comprendono:

/* Automatically created file - do not edit or ugly dinosaur will eat you */ 
#ifndef PREFIX 
# define RENAME(f) 
#else 
# define RENAME(f) PREFIX ## f 
#endif 

/* list all the function and variables you want to rename here in one place */ 
#define func_foo RENAME(func_foo) 
#define func_bar RENAME(func_bar) 
/* ... many more ... */ 

#undef RENAME 

Almeno gcc consente di specificare l'inclusione di un file di intestazione dalla riga di comando con l'opzione -include rename.h (presupponendo che questo file sia chiamato rename.h). Poiché si utilizzano le opzioni di sosia gcc (-O3 e Os), si presume che si usi gcc nel resto di questa risposta. Altrimenti, se il tuo compilatore C è ragionevole, dovresti essere in grado di farlo in un modo simile.

È possibile creare facilmente due o anche tre versioni della tua libreria che possono essere collegati in allo stesso tempo, se si desidera, fornendo diverse opzioni per il compilatore C (qui attraverso CFLAGS impostazione):

CFLAGS += -include rename.h -DPREFIX=fast_ -D_BUILD_FAST -O3 -DBENCHMARKING 
CFLAGS += -include rename.h -DPREFIX=small_ -D_BUILD_SMALL -Os -DBENCHMARKING 
CFLAGS += -D_BUILD_FAST -O2 

Se i file di intestazione della libreria sembrano molto regolari e se si dichiarano le funzioni private della libreria static, è facile estrarre le funzioni da tali file di intestazione da uno script fittizio utilizzando espressioni regolari molto semplici per generare automaticamente il file rename.h. Questo è un obiettivo di costruzione naturale se si utilizza make o qualcosa di simile. Anche tutte le variabili globali devono essere rinominate utilizzando lo stesso metodo per consentire l'uso simultaneo.

Ci sono tre punti principali con questa soluzione:

  1. Il business ridenominazione brutto può essere nascosta in un unico file, non è necessario modificare i file di origine effettivi - soprattutto non è necessario per il disordine i file sorgente ma possono tenerli puliti e facili da leggere.
  2. La ridenominazione può essere facilmente automatizzata, se si seguono alcuni semplici principi (le convenzioni di codifica seguite per i file di intestazione e i file di intestazione dichiarano tutte le variabili e le funzioni globali).
  3. Non c'è motivo di rendere più complicato il benchmark avendo bisogno di eseguire il programma di test più volte (questo è rilevante se si è pigri come me e non si piacciono le attività ripetitive con la stessa violenza che faccio - so che a molte persone non importa , è piuttosto una questione di preferenza).
+0

molto bello e risponde alla domanda, grazie! –

2

Un modo sarebbe: mantenere lo stesso nome per entrambi e chiamare in modo appropriato a seconda dell'impostazione dell'opzione di compilazione.

ifdef SMALL_FOO 
void foo() { 

/* Small foo code */ 
} 
#endif 

ifdef BIG_FOO 
void foo() { 

/* Big foo code */ 
} 
#endif 

Impostare la SMALL_FOO/BIG_FOO durante la compilazione con -d.

+0

L'avevo considerato. L'implementazione attuale richiederebbe alcune duplicazioni per farlo, ma penso che potrebbe essere fatto. –

0

Si dice che è possibile creare la libreria, modificando le opzioni di tempo di compilazione, quindi perché non modificare il codice per cambiare i nomi delle funzioni in ciascuno. (Sareste facendo due diverse versioni del tuo grimorio.)

+0

le opzioni di tempo di compilazione vengono passate al preprocessore, il codice non cambia (questo è comunque l'obiettivo). –

2

Come soluzione rapida, è possibile utilizzare macro per storpiare il nome della funzione come:

#ifdef FAST 
# define FUNC(x) FAST_##x 
#else 
# define FUNC(x) SLOW_##x 
#endif 

void FUNC(Foo)(); 

E ora con -DFAST biblioteca FAST_Foo volontà essere costruito; e senza di essa, uno con SLOW_Foo. Si noti che è necessario utilizzare la macro FUNC() anche nella parte di implementazione (e ogni volta che si fa riferimento a tale funzione dall'interno della libreria) e #ifdef FAST per passare tra codice veloce/lento.

Solo per favore non utilizzare quello in un codice di produzione.

+0

Vorrei anche aggiungere un '#ifdef ALIAS' che quando false aggirerebbe il precedente e nella clausola' # else' avremo '#define FUNC (x) x'. Quindi non è necessario utilizzare la macro nella parte di implementazione. –

+0

Stavo pensando a questo. Stavo cercando una soluzione di aliasing, ma avevo preso in considerazione la costruzione di specifiche funzioni di libreria "storpiate", quindi facendo un #ifdef FAST #define Foo FAST_Foo() #endif –

+0

Sono d'accordo con la ridenominazione, ma personalmente non mi piace come suggerito Qui. Non mi piace cambiare il modo in cui appaiono i prototipi di funzione. Non puoi più cercarli usando espressioni regolari, alcuni strumenti per gestire i file C si confondono e ingombrano la vista. Preferirei fare prima della definizione/dichiarazione della funzione. Ad esempio nell'esempio sopra, dite '#define Foo FUNC (Foo)' (usando le funzioni 'FUNC()' e 'Foo()' dove la macro 'FUNC()' dovrebbe essere meglio nominata diversamente se usata in questo modo) . Quindi puoi semplicemente avere un prototipo di funzione dall'aspetto normale. – FooF

2

Se si tenta di collegare entrambe le librerie statiche allo stesso file eseguibile, la seconda libreria elencata nella riga di collegamento non avrà alcun effetto, poiché tutti i simboli forniti sono già stati soddisfatti dalla prima libreria. Se hai fornito semplici funzioni wrapper univoche per chiamare Foo, fallirebbe, ora a causa di più definizioni. Ecco un esempio:

/* x.c */ 
extern void Y_Bar(); 
extern void Z_Bar(); 
int main() 
{ 
    Y_Bar(); 
    Z_Bar(); 
} 

This principali chiamate funzioni contenitore uniche, che sono forniti in liby.a e libz.a.

/* y.c in liby.a */ 
#include <stdio.h> 
void Y_Bar() { 
    extern void Foo(); 
    Foo(); 
} 
void Foo() { 
    printf("%s\n", "that Foo"); 
} 

/* z.c in libz.a */ 
#include <stdio.h> 
void Z_Bar() { 
    extern void Foo(); 
    Foo(); 
} 
void Foo() { 
    puts("this foo"); 
} 

Il tentativo di collegare l'eseguibile con -ly -lz avrà esito negativo.

Il metodo più semplice per voi è creare due file eseguibili separati. Il tuo driver di riferimento potrebbe quindi eseguire entrambi i file eseguibili per confrontare le prestazioni relative.

+0

L'ho selezionato come la soluzione più semplice per il codice di produzione. –

0

Forse è possibile utilizzare -D option when call gcc, like -D_FAST_, -D_SMALL_, o la vostra lattina ricevuto un parametro di input quando si usa fare, come l'uso di rendere CFG=FAST, make CFG=SMALL, nel vostro makefile, è possibile definire, se il parametro get FAST, link to FAST library.

Problemi correlati