2012-03-18 37 views
30

विंडोज़ में साझा लाइब्रेरी लोड करते समय, LoadLibrary() कॉल प्रत्येक नई प्रक्रिया और थ्रेड लाइब्रेरी अटैचमेंट के लिए निष्पादित करने के लिए लाइब्रेरी में DllMain का कारण बनता है, और प्रत्येक प्रक्रिया और थ्रेड लाइब्रेरी डिटैच के लिए।साझा पुस्तकालयों को लोड करते समय स्वचालित रूप से निष्पादित फ़ंक्शंस

क्या मैक ओएस एक्स, लिनक्स और संभवतः अन्य पॉज़िक्स-संगत ओएस के लिए समान तंत्र है?

+0

https://stackoverflow.com/q/2053029/4361073 – parasrish

उत्तर

42

आप .init तंत्र का उपयोग कर लिनक्स लाइब्रेरी के लिए ऑन-लोड फ़ंक्शन को परिभाषित कर सकते हैं। यह बाइनरी के लिए लोड-टाइम एंट्री पॉइंट निर्दिष्ट करने जैसा ही है (उदाहरण के लिए किसी प्रोग्राम के लिए प्रवेश बिंदु के रूप में मुख्य के अलावा कुछ अन्य का उपयोग करना)।

जब ld का उपयोग कर जोड़ने सीधे आप का उपयोग करें:

-init <function name> 

या आप लिंक करना सीसी/जीसीसी का उपयोग कर रहे हैं, तो आप का उपयोग करें:

-Wl,-init,<function name> 

यह सबसे सरल स्तर है पर है।

संपादित विनाशकर्ता/finalizers के लिए, आप .fini तंत्र का उपयोग करें। इस init विकल्प के रूप में एक ही तरीके से संचालित होता है, और आप का उपयोग करें:

-fini <function name> 

जब ld लागू। मैक ओएसएक्स मंच पर उपलब्धता -init विकल्प तक सीमित है।

तुम भी जीसीसी के लिए __attribute__((constructor)) सिंटैक्स का उपयोग करने में सक्षम होना चाहिए:

static void con() __attribute__((constructor)); 

void con() { 
    printf("I'm a constructor\n"); 
} 

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

संपादित करें 2__attribute__((constructor))/__attribute__((destructor)) अर्थात् का उपयोग सी/सी ++ प्रोग्रामिंग भाषा के लिए सबसे पसंदीदा तंत्र है।

D प्रोग्रामिंग भाषा क्या तुम सच में स्थिर मॉड्यूल निर्माता/नाशक का उपयोग करना चाहिए के लिए:

static this() { 
    printf("static this for mymodule\n"); 
} 
static ~this() { 
    printf("static ~this for mymodule\n"); 
} 

या स्थिर वर्ग निर्माता:

class Foo { 
    static this() { 
     printf("static this for Foo\n"); 
    } 
} 

यह दृढ़ता से writing win32 DLLS में और में की ओर संकेत किया गया है भाषा विनिर्देश relating to static constructors/destructors

संपादित 3 आप एक .o कि निर्माता/नाशक दिनचर्या निर्यात में लिंक करने के लिए, कि स्थिर initializers के उपयोग की अनुमति की आवश्यकता होगी। जैसा कि इसे करना चाहिए, Runtime.initialize() को कॉल करना है, यह वास्तव में D कोड में सभी स्थिर रचनाकारों/विनाशकों को आमंत्रित करता है।प्रारंभकर्ता के लिए

स्टब घ कोड (एक फ़ाइल में myshared.d कहा जाता है):

dmd -m32 -c myshared.d 

देते हैं/अलग कार्यों के नाम की जाँच करें:

import core.runtime; 

extern (C) { 
    void attach(); 
    void detach(); 
} 

export void attach() { 
    Runtime.initialize(); 
} 

export void detach() { 
    Runtime.terminate(); 
} 

इस ठूंठ के लिए ओ बनाएँ:

nm myshared.o 

शो (अन्य उत्पादन के अलावा):

+०१२३५१६४१०६ इस (इस मामले में कहा जाता export.c) लागू करने के लिए
0000001c S _D8myshared6attachFZv 
00000034 S _D8myshared6detachFZv 

नमूना ग कोड है, हम my shared.o फ़ाइल से निर्यात दिनचर्या के नाम का संदर्भ:

extern void D8myshared6attachFZv(void); 
extern void D8myshared6detachFZv(void); 

void __attach(void) __attribute__((constructor)); 
void __detach(void) __attribute__((destructor)); 

void __attach(void) 
{ 
    D8myshared6attachFZv(); 
} 

void __detach(void) 
{ 
    D8myshared6detachFZv(); 
} 

ध्यान दें कि extern void संदर्भ की जरूरत है निर्यात किए गए फ़ंक्शन के उलझन वाले नाम का उपयोग करें। ये मेल खाना चाहिए या कोड लिंक नहीं होगा।

का उपयोग कर सी कोड संकलन:

gcc -m32 -c export.c 

लिंक .c.o और .d.o फ़ाइलों का एक साथ उपयोग:

cc -o libmyshared.dylib -m32 -shared myshared.o export.o -lphobos2 

यह मानते हुए कि phobos2 पुस्तकालय अपने मानक लिंकर खोज पथ में है। कंपाइलर और लिंकर के लिए -m32 विकल्प की smatterings इसलिए हैं क्योंकि डी कंपाइलर का संस्करण जिसे मैंने स्थानीय रूप से बनाया है केवल 32 बिट का समर्थन किया है।

यह एक .dylib उत्पन्न करता है जिसे से जोड़ा जा सकता है। ऐसा लगता है कि मैंने किए गए सीमित परीक्षण के आधार पर काम किया है। ऐसा लगता है कि साझा वस्तुओं/गतिशील पुस्तकालयों के लिए समर्थन बहुत सीमित है, इसलिए एक अच्छा मौका है कि दूर करने के लिए एक और बाधा होगी।

+0

लगता है अपने समाधान है कि मेरे लिए सबसे स्वीकार्य है, क्योंकि मैं डी में लिख रहा हूं, सी में नहीं, और आपके समाधान में जीसीसी-विशिष्ट सामान शामिल नहीं है। इन कन्स्ट्रक्टर और विनाशक में बुलाए जाने वाली एकमात्र चीजें डी रनटाइम प्रारंभिकरण और समाप्ति हैं। – toriningen

+0

क्या आप यह भी संकेत दे सकते हैं कि विनाशकों को निर्दिष्ट करने के लिए एलडी ध्वज क्या है? – toriningen

+1

फाइनलाइज़र/विनाशक के बराबर -फिनी <फ़ंक्शन नाम> विकल्प का उपयोग करना है। – Petesh

9

एक समारोह निष्पादित जब भी शेयर की गई लाइब्रेरी लोड या अनलोड कर रहा है के लिए, आपको जीसीसी विशिष्ट विशेषता सिंटैक्स का उपयोग एक निर्माता और नाशक समारोह चिह्नित कर सकते हैं:

__attribute__((constructor)) void init(void) { ... } 
__attribute__((destructor)) void fini(void) { ... } 

क्योंकि एक सी पर्यावरण के विभिन्न भागों बातों पर निर्भर करती है दृश्यों के पीछे जीसीसी द्वारा जोड़े गए मानक .init कोड में प्रारंभ किया जा रहा है, सीधे -Wl,-init,<function name> का उपयोग करके आपके प्रोग्राम को क्रैश हो सकता है।

अधिक जानकारी के लिए, Library constructor and destructor functions पर लिबर हाउटो देखें।

0

सी ++ के लिए आप कक्षा बना सकते हैं और पुस्तकालय आरंभ करने के लिए अपने कन्स्ट्रक्टर और विनाशक का उपयोग कर सकते हैं।

इसके बाद, आपको केवल इस कक्षा के लिए एक चर परिभाषित करने की आवश्यकता है।पुस्तकालय में

उदाहरण आरंभ openssl:

class InitLibrary { 
public: 
    InitLibrary() { 
    CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use 
    SSL_library_init(); // Initialize OpenSSL's SSL libraries 
    SSL_load_error_strings(); // Load SSL error strings 
    ERR_load_BIO_strings(); // Load BIO error strings 
    OpenSSL_add_all_algorithms(); // Load all available encryption algorithms 
    } 

    ~InitLibrary() { 
    ERR_remove_state(0); 
    CRYPTO_cleanup_all_ex_data(); 
    ENGINE_cleanup(); 
    } 
}; 

और केवल cpp फ़ाइल में इस पंक्ति जोड़ें: InitLibrary InitLib;

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

  • कोई संबंधित समस्या नहीं^_^