2014-10-02 7 views
21

मुझे आश्चर्य है कि सी ++ 11/14 में वास्तव में संकलन समय पर फ़ाइलों को पढ़ने के लिए यह संभव है या नहीं। उदाहरण के लिए निम्न कोड केवल तभी संकलित होगा यदि यह फ़ाइल को सफलतापूर्वक पढ़ सके।संकलन समय पर एक फ़ाइल को पढ़ना संभव है?

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

क्या आपको लगता है कि यह संभव हो सकता है?

मुझे पता है कि मैं अपने आवेदन के निर्माण के दौरान कुछ कस्टम टूल के साथ ऐसा कर सकता हूं।

+6

यह * लोड * द्वारा आप जो भी पहनते हैं उस पर निर्भर करता है। मुझे पता है कि एकमात्र समाधान '# शामिल' है, और इसका मतलब है कि फ़ाइल की सामग्री को कंपाइलर द्वारा समझा जाना चाहिए। –

+6

जो आप शायद चाहते हैं वह बाह्य परिवर्तनीय घोषणा है, जो लिंकर द्वारा वास्तविक डेटा से मेल खाया जाएगा। उस उपकरण के साथ संयोजित करें जो किसी ऑब्जेक्ट फ़ाइल में अपनी पसंद के निर्यात किए गए प्रतीक के साथ एक मनमानी बाइनरी संसाधन को एम्बेड करता है, और आप सुनहरे हैं। (मैं इस तरह के एक उपकरण का सुझाव दे सकता था, लेकिन आपने यह नहीं बताया कि आप किस टूलचैन का उपयोग कर रहे हैं, और उपकरण ईएलएफ बनाम सीवी बनाम पीई बनाम ऑब्जेक्ट फ़ाइल स्वरूपों के लिए अलग हैं) ध्यान दें कि संसाधन को सी/सी ++ कोड में परिवर्तित करना हेक्साडेसिमल अक्षरों के साथ शुरू की गई एक स्थिर सरणी बहुत धीमी होने की संभावना है, इसलिए सीधे ऑब्जेक्ट फ़ाइल पर जाएं। –

+0

मुझे विश्वास नहीं है कि आपका 'लोड' फ़ंक्शन' कॉन्स्टेक्स 'है। तो पूरी अभिव्यक्ति constexpr नहीं हो सकता है। मुझे नहीं पता कि बाहरी फ़ाइल सामग्री एक constexpr स्ट्रिंग कैसे हो सकती है।एकमात्र तरीका एक उपकरण का उपयोग करना है जो फ़ाइल को सरल लोड करता है और सी/सी ++ कोड उत्पन्न करता है। – Klaus

उत्तर

16

teivaz के विचार पर बिल्डिंग संभाल लेंगे, मुझे आश्चर्य है अगर हमेशा की तरह "stringize विस्तार के बाद" चाल काम करेगा:

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

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


फिर भी, मैं एक पारंपरिक extern const char[] लिंकर द्वारा सामग्री के लिए घोषित घोषणा के लिए जाना होगा।

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

स्वाभाविक रूप से आप --output और --binary-architecture आदेशों अपने मंच से मिलान करने बदलना चाहिए: लेख "Embedding a File in an Executable, aka Hello World, Version 5967" एक उदाहरण है। ऑब्जेक्ट फ़ाइल से फ़ाइल नाम प्रतीक नाम में समाप्त होता है, इसलिए आप इसका उपयोग इस प्रकार कर सकते हैं:

#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

लेकिन इंटरजे के मुताबिक, यह जीएलएसएल में कॉमा के कारण टूट सकता है। –

+0

मैंने इसे चेक किया है। shader_sourc ई में '# शामिल "होगा// .foo.glsl" ' – teivaz

+0

@teivaz: यहां तक ​​कि दो-परत मैक्रो आमंत्रण के साथ भी? –

-1
#define STR(x) #x 

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

और foo.glsl एसटीआर ( ... )

upd में अपनी सामग्री जोड़ देना चाहिए। यह ठीक से अल्पविराम के

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

प्रीप्रोसेसर घोषणाएं जैसे कि # # शामिल 'लाइन पर पहली गैर-व्हाइटस्पेस होना चाहिए :( –

+0

लेकिन http://stackoverflow.com/a/5566624/103167 देखें। ब्रांड्स और '# शामिल' के बीच एक नई लाइन डालना ठीक रहेगा, जब तक कि डेटा प्रारूप स्ट्रिंग में दिखाई देने वाली उन अतिरिक्त न्यूलाइनों का सहिष्णु है (जीएलएसएल सहिष्णु है)। –

+0

हम्म, आपके संपादन ने प्रीप्रोसेसर आमंत्रण को ठीक किया लेकिन टूट गया स्ट्रिंगिंग। –

0

मैंने ऐसा कुछ किया है। देखें कि यह आपको वही देगा जो आप चाहते हैं।

प्रोग्राम में एक कमांड लाइन विकल्प जोड़ें जो इनपुट फ़ाइल के अस्तित्व और वैधता की जांच करता है।
यदि फ़ाइल मौजूद नहीं है, या वैध नहीं है, तो उस विकल्प को प्रोग्राम को त्रुटि कोड के साथ बाहर निकलना चाहिए।

अपनी मेक फ़ाइल में, अंतिम निर्माण चरण के रूप में प्रोग्राम (उस कमांड लाइन विकल्प का उपयोग करके) में एक कॉल जोड़ें।

अब जब आप प्रोग्राम बनाते हैं, तो उचित फाइलें उपलब्ध नहीं हैं या मान्य नहीं होने पर आपको एक त्रुटि मिलेगी।

+0

वह बाहरी कार्यक्रमों से बचना चाहता है। – Deduplicator

संबंधित मुद्दे