2009-06-04 8 views
8

सुनिश्चित करने के लिए है कि कुछ प्रवर्तन कोड से पहले main (Arduino/AVR-जीसीसी उपयोग करते हुए) मैं कोड है चलाता है जैसे निम्नलिखित:मैं एआरआर-जीसीसी के साथ सी/सी ++ में प्री-मुख्य प्रारंभिक प्रदर्शन कैसे कर सकता हूं?

class Init { 
public: 
    Init() { initialize(); } 
}; 

Init init; 

आदर्श रूप में मैं चाहता हूँ बस लिखने के लिए सक्षम होने के लिए:

initialize(); 

लेकिन इस संकलन नहीं करता है ...

वहाँ एक ही प्रभाव को प्राप्त करने के लिए एक कम वर्बोज़ रास्ता नहीं है?

नोट: कोड एक Arduino स्केच तो main समारोह स्वचालित रूप से उत्पन्न होता है का हिस्सा है और बदला नहीं जा सकता है (उदाहरण के किसी अन्य कोड से पहले initialize कॉल करने के लिए)।

अद्यतन: आदर्श प्रारंभ setup समारोह में प्रदर्शन किया जा सकता है, लेकिन इस मामले में वहाँ जो main से पहले होता है यह आधार पर अन्य कोड है।

उत्तर

11

आप सुनिश्चित करने के लिए यह कहा जाता हो जाता है कि जीसीसी के constructor attribute उपयोग कर सकते हैं main() से पहले:

void Init(void) __attribute__((constructor)); 
void Init(void) { /* code */ } // This will always run before main() 
+0

+1 सरल और साफ। क्या यह निश्चित रूप से avr-gcc पर भी काम करता है? –

+0

मुझे यकीन नहीं है, क्योंकि मैंने कभी भी avr-gcc का उपयोग नहीं किया है, लेकिन इस पृष्ठ के अनुसार http://www.nongnu.org/avr-libc/user-manual/porting.html, avr-gcc समर्थन करता है अन्य प्रकार के गुण। –

+1

मैंने Arduino सॉफ़्टवेयर (जिसे avr-gcc द्वारा समर्थित किया गया है) का उपयोग करके यह कोशिश की है और यह काम करता है। मैं यह जवाब स्वीकार करूंगा, धन्यवाद। –

2

सरल और साफ में आपका समाधान। आप अतिरिक्त रूप से क्या कर सकते हैं अपने कोड को अनाम नामस्थान में रखना है। मैं यह है कि :) की तुलना में बेहतर बनाने के लिए किसी भी आवश्यकता नहीं दिख रहा है

+0

किसी अज्ञात नेमस्पेस में इसे लपेटने से संभवतः कक्षा के नाम को रोक दिया जाएगा और इसके उदाहरण नामस्थान को प्रदूषित कर देगा (जो एक अच्छी बात है) लेकिन यह वास्तव में कोड को कम वर्बोज़ बनाने में मदद नहीं करता है ... –

0

ज़रूर, आप अपने अपने हेडर फाइल में से एक में यह डाल दिया, कहते हैं कि preinit.h:

class Init { public: Init() { initialize(); } }; Init init; 

और फिर, एक में अपने संकलन इकाइयों की, डाल:

void initialize(void) { 
    // weave your magic here. 
} 
#include "preinit.h" 

मुझे पता है कि एक kludge है, लेकिन मैं एक वर्ग निर्माता फ़ाइल गुंजाइश पर क्रियान्वित का उपयोग किए बिना पूर्व मुख्य प्रारंभ करने के लिए कोई पोर्टेबल रास्ता के बारे में पता नहीं कर रहा हूँ।

आपको इन प्रारंभिक कार्यों में से एक से अधिक को शामिल करने से भी सावधान रहना चाहिए क्योंकि मुझे विश्वास नहीं है कि सी ++ आदेश को निर्देशित करता है - यह यादृच्छिक हो सकता है।

मैं इस "स्केच" जो की आप बात का यकीन नहीं है, लेकिन यह यह संकलक के लिए पारित होने से पहले एक स्क्रिप्ट के साथ मुख्य संकलन इकाई को बदलने के लिए संभव हो जाएगा, कुछ की तरह:

awk '{print;if (substr($0,0,11) == "int main (") {print "initialize();"};}' 

आप देख सकते हैं कि यह कैसे अपने कार्यक्रम को प्रभावित करती है क्योंकि:

echo '#include <stdio.h> 
int main (void) { 
    int x = 1; 
    return 0; 
}' | awk '{ 
    print; 
    if (substr($0,0,11) == "int main (") { 
     print " initialize();" 
    } 
}' 

उत्पन्न initialize() कॉल के साथ निम्नलिखित कहा:

#include <stdio.h> 
int main (void) { 
    initialize(); 
    int x = 1; 
    return 0; 
} 

ऐसा हो सकता है कि आप जेनरेट की गई फ़ाइल को पोस्ट-प्रोसेस नहीं कर सकते हैं, इस मामले में आपको उस अंतिम विकल्प को अनदेखा करना चाहिए, लेकिन यही वह है जो मैं पहले देख रहा हूं।

+0

एक समाधान नहीं करता है ' पोर्टेबल होने की जरूरत नहीं है। इसे केवल avr-gcc का उपयोग करके काम करने की आवश्यकता है। –

0

कक्षाओं के स्थिर सदस्यों का उपयोग करें। मुख्य में प्रवेश करने से पहले उन्हें प्रारंभ किया जाता है। नुकसान यह है कि आप स्थैतिक वर्ग के सदस्यों के प्रारंभिकरण के आदेश को नियंत्रित नहीं कर सकते हैं।

यहाँ अपने उदाहरण तब्दील हो जाता है:

class Init { 
private: 
    // Made the constructor private, so to avoid calling it in other situation 
    // than for the initialization of the static member. 
    Init() { initialize(); } 

private: 
    static Init INIT; 
}; 


Init Init::INIT; 
+3

यह अधिक वर्बोज़ है, कम नहीं। –

+0

यह विचार मुझे आश्चर्यचकित करता है कि कक्षा * पदानुक्रम * में स्थिर सदस्यों के प्रारंभिकरण के क्रम को सी ++ में परिभाषित किया गया है? यदि ऐसा है तो "स्थिर प्रारंभिक आदेश फियास्को" से निपटने का एक तरीका होगा। –

+0

@ पियोटर: अनुवाद इकाई में प्रारंभिकरण का क्रम "परिभाषाओं को प्रकट करने के क्रम" के रूप में परिभाषित किया गया है। अनुवाद इकाइयों के बीच इसकी अपरिभाषित। –

2

आप Arduino वातावरण का उपयोग कर रहे हैं, तो ऐसा कोई कारण आप setup method में रख नहीं कर सकता है?

बेशक, यह Arduino- विशिष्ट हार्डवेयर सेटअप के बाद है, इसलिए यदि आपके पास ऐसी निम्न-स्तरीय सामग्री है जो इसे वास्तव में main से पहले जाना है, तो आपको कुछ कन्स्ट्रक्टर जादू की आवश्यकता है।

अद्यतन:

ठीक है, इसे किया जा करने के लिए मुख्य से पहले मुझे लगता है कि एक ही रास्ता एक निर्माता की तरह उपयोग करने के लिए आप पहले से ही कर रखता है।

#define RUN_EARLY(code) \ 
namespace { \ 
    class Init { \ 
     Init() { code; } \ 
    }; \ 
    Init init; \ 
} 

अब इस काम करना चाहिए:

तुम हमेशा इसके बारे में एक पूर्वप्रक्रमक मैक्रो बना सकते हैं

RUN_EARLY(initialize()) 

लेकिन यह वास्तव में, बातें कम कर रही है बस के चारों ओर वर्बोज़ कोड का स्थान बदलना नहीं है।

+0

+1, लेकिन दुर्भाग्य से मैं इसके लिए सेटअप() का उपयोग नहीं कर सकता। मैं इसे स्पष्ट करने के लिए प्रश्न अपडेट करूंगा। –

4

आप उपरोक्त बहुत थोड़ा दे रही है "प्रारंभ" एक वापसी प्रकार, और एक वैश्विक चर प्रारंभ करने का उपयोग कर कम कर सकते हैं:

int initialize(); 
int dummy = initialize(); 

हालांकि, अगर आप इस के साथ सावधान रहना चाहिए, मानक करता है गारंटी नहीं है कि इसके बाद के संस्करण प्रारंभ (या अपने init वस्तु के लिए एक) जगह लेता से पहले मुख्य (3.6.2/3) चलाया जाता है:

यह कार्यान्वयन-परिभाषित किया गया है या नहीं, गतिशील प्रारंभ (8.5, 9.4 , 12.1, 12.6.1) नामस्थान स्कोप की एक वस्तु का माई के पहले बयान से पहले किया जाता है एन।

एकमात्र चीज जो गारंटी है वह है कि 'डमी' का उपयोग कभी भी शुरू होने से पहले किया जाएगा।

एक अधिक घुसपैठ विकल्प (यदि यह संभव है) आपके मेकफ़ाइल में "-D main = avr_main" का उपयोग करना हो सकता है। इसके बाद आप अपना मुख्य मुख्य रूप निम्नानुसार जोड़ सकते हैं:

// Add a declaration for the main declared by the avr compiler. 
int avr_main (int argc, const char * argv[]); // Needs to match exactly 

#undef main 
int main (int argc, const char * argv[]) 
{ 
    initialize(); 
    return avr_main (argc, argv); 
} 

कम से कम यहां आपको गारंटी है कि जब आप उम्मीद करते हैं तो प्रारंभिकता होगी।

#include <stdio.h> 

static int bar = 0; 

int __real_main(int argc, char **argv); 

int __wrap_main(int argc, char **argv) 
{ 
    bar = 1; 
    return __real_main(argc, argv); 
} 

int main(int argc, char **argv) 
{ 
    printf("bar %d\n",bar); 
    return 0; 
} 

लिंकर झंडे के लिए निम्न जोड़ें:: --wrap main

जैसे

+0

दुर्भाग्यवश Arduino पर्यावरण कंपाइलर के निष्पादन को नियंत्रित करता है इसलिए कोई मेकफ़ाइल नहीं है जिसे मैं बदल सकता हूं। –

3

यहाँ इस को प्राप्त करने का एक हद तक बुराई विधि है।

gcc -Xlinker --wrap -Xlinker main a.c 

लिंकर __wrap_main के लिए कॉल के साथ main के लिए सभी कॉल का स्थान ले लेगा, देखना ld man page पर --wrap

+0

दुर्भाग्यवश मेरे पास जीसीसी (वास्तव में avr-gcc) कमांड लाइन पर कोई नियंत्रण नहीं है क्योंकि यह Arduino पर्यावरण द्वारा स्वचालित रूप से संभाला जाता है। –

2

मुख्य() और यहां तक ​​कि सी रनटाइम से पहले चलाने के लिए सी कोड जोड़ने के लिए आप ".init *" सेक्शन का उपयोग कर सकते हैं। इन वर्गों को अंत में निष्पादन योग्य में जोड़ा गया है और कार्यक्रम प्रारंभिकरण के दौरान विशिष्ट समय पर बुलाया गया है।) उदाहरण के लिए

http://www.nongnu.org/avr-libc/user-manual/mem_sections.html

.init1 कमजोर __init के लिए बाध्य है (, इसलिए यदि आप __init() को परिभाषित है, यह लिंक किया जाएगा और पहली बात यह कहा जाता है: आप यहाँ सूची प्राप्त कर सकते हैं। हालांकि, स्टैक सेटअप नहीं किया गया है, इसलिए आपको जो करना है उसमें सावधान रहना होगा (केवल रजिस्टर 8_t चर का उपयोग करें, किसी भी फ़ंक्शन को कॉल न करें)।

0

मैं प्री-मुख्य कोडिंग कैसे करता हूं। मुख्य से पहले निष्पादित सेवर इनिट अनुभाग हैं, http://www.nongnu.org/avr-libc/user-manual/mem_sections.html initN अनुभागों को संदर्भित करता है।

किसी भी तरह, यह केवल कुछ कारणों से -O0 अनुकूलन पर काम करता है। मैं अभी भी यह पता लगाने की कोशिश करता हूं कि कौन सा विकल्प मेरे पूर्व-मुख्य असेंबली कोड को "अनुकूलित" करता है।

static void 
__attribute__ ((naked)) 
__attribute__ ((section (".init8"))) /* run this right before main */ 
__attribute__ ((unused)) /* Kill the unused function warning */ 
stack_init(void) {assembly stuff} 

अद्यतन, यह पता चला है मैं दावा किया इस समारोह अप्रयुक्त है, दिनचर्या दूर अनुकूलन करने के लिए अग्रणी। मेरा उद्देश्य अप्रयुक्त चेतावनी को मारने का इरादा था। यह इसके बजाय इस्तेमाल की गई विशेषता का उपयोग करने के लिए तय है।

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

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