2014-10-02 17 views
21

Mi chiedo se sia possibile in C++ 11/14 leggere effettivamente i file in fase di compilazione. Ad esempio il seguente codice verrà compilato solo se può leggere correttamente il file.È possibile leggere un file in fase di compilazione?

constexpr std::string shader_source = load("~/foo.glsl"); 

Pensi che questo sia possibile?

So che potrei farlo con qualche strumento personalizzato quando costruisco la mia applicazione.

+6

Dipende da cosa si svezza per * caricare *. L'unica soluzione che conosco è '# include', e significa che il contenuto del file deve essere compreso dal compilatore. –

+6

Ciò che si desidera è una dichiarazione di variabile esterna, che verrà abbinata ai dati effettivi dal linker. Combina questo con uno strumento che incorpora una risorsa binaria arbitraria in un file oggetto con un simbolo esportato di tua scelta, e sei d'oro. (Potrei suggerire un tale strumento, ma non hai menzionato quale toolchain stai usando, e gli strumenti sono diversi per i formati di file oggetto ELF vs CV vs PE vs.out) Nota che convertire la risorsa in codice C/C++ come un array costante inizializzato con letterali esadecimali è molto lento, quindi vai direttamente al file oggetto. –

+0

Non posso credere che la funzione 'load' sia un' constexpr'. Quindi l'espressione completa non può essere constexpr. Non ho idea di come un contenuto di file esterno possa essere una stringa di constexpr.L'unico modo è utilizzare uno strumento che carica il file e genera codice c/C++. – Klaus

risposta

16

della costruzione su idea di teivaz, mi chiedo se il solito "stringize dopo l'espansione" trucco funziona:

#define STRINGIZE(...) #__VA_ARGS__ 
#define EXPAND_AND_STRINGIZE(...) STRINGIZE(__VA_ARGS__) 

constexpr std::string shader_source = EXPAND_AND_STRINGIZE(
#include "~/.foo.glsl" 
); 


Eppure, andrebbe per una dichiarazione convenzionale extern const char[] risolta al contenuto dal linker. L'articolo "Embedding a File in an Executable, aka Hello World, Version 5967" ha un esempio:

# objcopy --input binary \ 
      --output elf32-i386 \ 
      --binary-architecture i386 data.txt data.o 

Naturalmente è necessario modificare il --output e --binary-architecture comandi per abbinare la vostra piattaforma. Il nome file dal file oggetto finisce nel nome del simbolo, quindi puoi usarlo in questo modo:

#include <stdio.h> 

/* here "data" comes from the filename data.o */ 
extern "C" char _binary_data_txt_start; 
extern "C" char _binary_data_txt_end; 

main() 
{ 
    char* p = &_binary_data_txt_start; 

    while (p != &_binary_data_txt_end) putchar(*p++); 
} 
+0

Ma come sottolinea Interjay, questo potrebbe rompersi a causa di virgole nel GLSL. –

+0

Ho controllato. shader_sourc e conterrà '#include" ~/.foo.glsl "' – teivaz

+0

@teivaz: anche con la chiamata macro a due livelli? –

-1
#define STR(x) #x 

const char* a = 
{ 
#include "foo.glsl" 
}; 

e foo.glsl dovrebbe racchiudere il contenuto in STR ( ... )

upd. In questo modo di gestire correttamente le virgole

#define STRINGIFY(...) #__VA_ARGS__ 
#define STR(...) STRINGIFY(__VA_ARGS__) 
+4

Le dichiarazioni di preprocessore come '# include' devono essere il primo non-spazio sulla linea :( –

+0

Ma vedere http://stackoverflow.com/a/5566624/103167. sarà ok per mettere una newline tra parentesi e '# include', a condizione che il formato dei dati sia tollerante rispetto a quelle nuove extra che appaiono nella stringa (GLSL è tollerante) –

+0

Hmm, la tua modifica ha risolto il richiamo del preprocessore ma si è rotto stringing –

0

Ho fatto qualcosa del genere. Vedi se questo ti darà quello che vuoi.

Aggiungere un'opzione della riga di comando al programma che verifica l'esistenza e la validità del file di input.
Questa opzione dovrebbe uscire dal programma con un codice di errore se il file non esiste o non è valido.

Nel file di creazione, aggiungere una chiamata al programma (utilizzando l'opzione della riga di comando), come passaggio finale di creazione.

Ora quando si crea il programma, si otterrà un errore se i file appropriati non sono disponibili o non sono validi.

+0

Vuole evitare i programmi esterni. – Deduplicator

Problemi correlati