फ़ंक्शंस के रनटाइम आयात की अनुमति के लिए C ++ प्रोग्राम कैसे डिज़ाइन करें?


10

आज, मैं आपको एक विशिष्ट सॉफ्टवेयर आर्किटेक्चर का एहसास करने के लिए C ++ की क्षमताओं के बारे में एक प्रश्न पूछना चाहता हूं।

बेशक, मैंने खोज का उपयोग किया है, लेकिन कोई सीधा जुड़ा हुआ उत्तर नहीं मिला है।

मूल रूप से, मेरा लक्ष्य एक ऐसे कार्यक्रम का निर्माण करना है जो उपयोगकर्ता को मॉडलिंग और मनमाने ढंग से बनाए गए भौतिक सिस्टम के अनुकरण की अनुमति देता है, जैसे ड्राइविंग कार। मुझे लगता है कि भौतिक मॉडल (कक्षाओं के भीतर कार्य) का एक पुस्तकालय है। प्रत्येक फ़ंक्शन में कुछ इनपुट हो सकते हैं और अंतर्निहित शारीरिक विवरण के आधार पर कुछ आउटपुट लौटा सकते हैं, जैसे एक दहन इंजन मॉडल, एक वायुगतिकीय ड्रैग मॉडल, एक पहिया मॉडल, आदि।

अब, विचार उपयोगकर्ता को एक ढांचा प्रदान करना है जो उसे अपनी आवश्यकताओं के अनुसार किसी भी कार्य को करने की अनुमति देता है, अर्थात किसी भी भौतिक व्यवहार को मैप करने के लिए। फ्रेमवर्क को विभिन्न कार्यों के आउटपुट और इनपुट को जोड़ने के लिए कार्यक्षमता प्रदान करनी चाहिए। इसलिए, फ्रेमवर्क एक कंटेनर क्लास प्रदान करता है। मैं इसे घटक कहता हूं, जो एक या कई मॉडल ऑब्जेक्ट (FUNCTION) को धारण करने में सक्षम है। ये कंटेनर अन्य घटकों (cf. मिश्रित पैटर्न) के साथ-साथ फ़ंक्शन पैरामीटर के बीच कनेक्शन (कनेक्टर) भी पकड़ सकते हैं। इसके अतिरिक्त, घटक वर्ग कुछ सामान्य संख्यात्मक कार्यक्षमताएं प्रदान करता है जैसे कि गणित सॉल्वर और इसी तरह।

कार्यों की संरचना रनटाइम के दौरान की जानी चाहिए। पहले उदाहरण में, उपयोगकर्ता को एक XML आयात करने के माध्यम से एक रचना स्थापित करने में सक्षम होना चाहिए जो संरचना संरचना को परिभाषित करता है। बाद में, कोई GUI जोड़ने के बारे में सोच सकता है।

आपको यहां एक बेहतर समझ देने के लिए एक बहुत ही सरल उदाहरण दिया गया है:

<COMPONENT name="Main">
  <COMPONENT name="A">
    <FUNCTION name="A1" path="lib/functionA1" />
  </COMPONENT>
  <COMPONENT name="B">
    <FUNCTION name="B1" path="lib/functionB1" />
    <FUNCTION name="B2" path="lib/functionB2" />
  </COMPONENT>
  <CONNECTIONS>
    <CONNECTOR source="A1" target="B1" />
    <CONNECTOR source="B1" target="B2" />
  </CONNECTIONS>        
</COMPONENT>

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

मैं प्रतिबिंब के सिद्धांतों को जानता हूं और मुझे पता है कि C ++ यह सुविधा प्रदान नहीं करता है। हालांकि, मुझे यकीन है कि "रनटाइम के दौरान वस्तुओं का निर्माण" की अवधारणा बहुत बार आवश्यक है। मुझे अपना लक्ष्य प्राप्त करने के लिए C ++ में अपना सॉफ़्टवेयर आर्किटेक्चर कैसे सेट करना चाहिए? क्या C ++ सही भाषा है? मैं क्या अनदेखी करता हूं?

अग्रिम में धन्यवाद!

चीयर्स, ओलिवर


C ++ में फंक्शन पॉइंटर्स और फंक्शन ऑब्जेक्ट्स हैं। क्या सभी कार्यों को निष्पादन योग्य में संकलित किया गया है, या वे गतिशील पुस्तकालयों में हैं (किस मंच पर)?
कैलथ

1
यह सवाल इस अर्थ में भी व्यापक है कि इसे आमतौर पर इलेक्ट्रिकल इंजीनियरिंग / [इलेक्ट्रॉनिक डिजाइन ऑटोमेशन (EDA)] ( en.wikipedia.org/wiki/Electronic_design_automation ) या मैकेनिकल इंजीनियरिंग / कंप्यूटर एडेड डिजाइन (CAD) में विश्वविद्यालय की डिग्री की आवश्यकता होती है । तुलनात्मक रूप से, C / C ++ डायनामिक लाइब्रेरी को कॉल करना बहुत आसान है, C86 को x86 के लिए कॉलिंग कन्वेंशन देखें । यद्यपि इसके लिए स्टैक (सीपीयू स्टैक पॉइंटर के माध्यम से) और सीपीयू रजिस्टर मानों में हेरफेर करने की आवश्यकता हो सकती है।
रॉव

1
गतिशील रूप से लोडिंग फ़ंक्शन C ++ भाषा द्वारा समर्थित नहीं है। आप कुछ प्लेटफ़ॉर्म-विशिष्ट देखने जा रहे हैं। उदाहरण के लिए विंडोज पर C ++ कंपाइलर को Windows DLL का समर्थन करना चाहिए, जो प्रतिबिंब के एक रूप का समर्थन करता है।
साइमन बी

C ++ में एक फ़ंक्शन को कॉल करना वास्तव में कठिन है जिसके हस्ताक्षर (तर्क और वापसी प्रकार) संकलन समय पर ज्ञात नहीं हैं। ऐसा करने के लिए, आपको यह जानना होगा कि आपके चुने हुए प्लेटफ़ॉर्म के असेंबली स्तर पर फ़ंक्शन कॉल कैसे काम करती है।
बार्ट वैन इनगेन शेनौ

2
जिस तरह से मैं इसे हल करता हूं वह है सी + + कोड को संकलित करना जो किसी भी भाषा के लिए एक दुभाषिया बनाता है जो एक eval कमांड का समर्थन करता है। C ++ का उपयोग करके बैंग समस्या हल की गई। : पी कृपया इस बारे में सोचें कि यह क्यों अच्छा नहीं है और प्रश्न को अपडेट करें। वास्तविक आवश्यकताओं के स्पष्ट होने पर यह मदद करता है।
कैंडिड_ओरेंज

जवाबों:


13

शुद्ध मानक C ++ में, आप "फ़ंक्शन के रनटाइम आयात की अनुमति नहीं दे सकते"; मानक के अनुसार, C ++ फ़ंक्शंस का सेट सांख्यिकीय रूप से बिल्ड-टाइम (व्यवहार में, लिंक-टाइम) के बाद से जाना जाता है क्योंकि आपके प्रोग्राम की रचना करने वाली सभी अनुवाद इकाइयों के मिलन से तय होता है ।

व्यवहार में, अधिकांश समय (एम्बेडेड सिस्टम को छोड़कर) आपका C ++ प्रोग्राम कुछ ऑपरेटिंग सिस्टम के ऊपर चलता हैऑपरेटिंग सिस्टम पढ़ें : एक अच्छे अवलोकन के लिए तीन आसान टुकड़े

कई आधुनिक ऑपरेटिंग सिस्टम प्लगइन्स के गतिशील लोडिंग की अनुमति देते हैं । POSIX विशेष रूप से और निर्दिष्ट करता है । विंडोज में कुछ अलग है (और एक अवर लिंकिंग मॉडल; आपको संबंधित कार्यों को स्पष्ट रूप से एनोटेट करने की आवश्यकता है, प्रदान या प्लगइन्स द्वारा उपयोग किया जाता है)। लिनक्स पर BTW आप व्यावहारिक रूप से बहुत सारे प्लगइन्स को देख सकते हैं (मेरा प्रोग्राम देखें , पर्याप्त धैर्य के साथ यह लगभग एक मिलियन प्लगइन्स को लोड कर सकता है)। इसलिए आपकी XML चीज प्लगइन्स की लोडिंग को ड्राइव कर सकती है। आपका बहु-घटक / बहु-कनेक्टर विवरण मुझे क्यूटी संकेतों और स्लॉट्स की याद दिलाता है (जिसके लिए आपको एक पूर्वप्रक्रमक की आवश्यकता होती है ; आपको ऐसा कुछ भी करने की आवश्यकता हो सकती है)।dlopendlsymLoadLibrarydlopenmanydl.cmoc

अधिकांश C ++ कार्यान्वयन नाम प्रबंध का उपयोग करते हैं । इसके कारण, आप बेहतर तरीके extern "C"से प्लगइन्स से संबंधित कार्य (और उनमें परिभाषित, और dlsymमुख्य प्रोग्राम से एक्सेस ) के रूप में घोषित करेंगे । C ++ dlopen mini HowTo (लिनक्स के लिए कम से कम) पढ़ें ।

BTW, Qt और POCO C ++ चौखटे हैं जो प्लगइन्स को कुछ पोर्टेबल और उच्च-स्तरीय दृष्टिकोण प्रदान करते हैं। और libffi आपको उन फ़ंक्शन को कॉल करने में सक्षम करता है जिनके हस्ताक्षर केवल रनटाइम पर ज्ञात हैं।

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

उन तरीकों के वेरिएंट या मिक्स हैं। आप कुछ JIT संकलन पुस्तकालय (जैसे libgccjit या asmjit) का उपयोग कर सकते हैं । आप एक अस्थायी फ़ाइल में कुछ सी और सी ++ कोड रनटाइम पर उत्पन्न कर सकते हैं , इसे एक अस्थायी प्लगइन के रूप में संकलित कर सकते हैं, और गतिशील रूप से उस प्लगइन को लोड कर सकते हैं (मैंने जीसीसी एमईएलटी में इस तरह के दृष्टिकोण का उपयोग किया था )।

इन सभी दृष्टिकोणों में, स्मृति प्रबंधन एक महत्वपूर्ण चिंता है (यह एक "संपूर्ण कार्यक्रम" संपत्ति है, और वास्तव में आपके कार्यक्रम का "लिफाफा" "बदलना" है)। आपको कचरा संग्रहण के बारे में कम से कम कुछ संस्कृति की आवश्यकता होगी । शब्दावली के लिए जीसी हैंडबुक पढ़ें । कई मामलों में (मनमाने ढंग से परिपत्र संदर्भ जहां कमजोर संकेत अनुमानित नहीं हैं), C ++ स्मार्ट पॉइंटर्स के लिए प्रिय संदर्भ योजना पर्याप्त नहीं हो सकती है। यह भी देखें इस

डायनामिक सॉफ़्टवेयर अपडेट के बारे में भी पढ़ें ।

ध्यान दें कि कुछ प्रोग्रामिंग लैंग्वेज, विशेष रूप से कॉमन लिस्प (और स्मॉलटॉक ), रनटाइम इंपोर्टिंग फंक्शंस के विचार के अधिक अनुकूल हैं। SBCL आम लिस्प का एक मुफ्त सॉफ्टवेयर कार्यान्वयन है, और प्रत्येक REPL बातचीत में मशीन कोड के लिए संकलित करता है (और यहां तक ​​कि मशीन कोड इकट्ठा करने में भी सक्षम है, और एक संपूर्ण कोर छवि फ़ाइल को बचा सकता है जिसे बाद में आसानी से पुनरारंभ किया जा सकता है)।


3

स्पष्ट रूप से आप अपनी खुद की स्टाइल सिमुलिंक या लैबव्यू टाइप सॉफ्टवेयर को रोल करने की कोशिश कर रहे हैं, लेकिन एक अपवित्र XML घटक के साथ।

इसके सबसे बुनियादी में, आप एक ग्राफ-उन्मुख डेटा संरचना की तलाश कर रहे हैं। आपके भौतिक मॉडल नोड्स से बने होते हैं (आप उन्हें घटक कहते हैं), और किनारों (आपके नामकरण में कनेक्टर्स)।

ऐसा करने के लिए कोई भाषा लागू तंत्र नहीं है, यहां तक ​​कि प्रतिबिंब के साथ भी नहीं, इसलिए इसके बजाय आपको एक एपीआई बनाना होगा और जो भी घटक खेलना चाहता है उसे कई कार्यों को लागू करना होगा और अपने एपीआई द्वारा निर्धारित नियमों का पालन करना होगा।

प्रत्येक घटक को सामान करने के लिए कार्यों के एक सेट को लागू करने की आवश्यकता होगी:

  • घटक का नाम या इसके बारे में अन्य विवरण प्राप्त करें
  • कितने एक्सपोजर या आउटपुट घटक को उजागर करता है की संख्या प्राप्त करें
  • एक विशेष इनपुट हमारे आउटपुट के बारे में एक घटक से पूछताछ करें
  • इनपुट और आउटपुट को एक साथ कनेक्ट करें
  • और दूसरे

और यह सिर्फ अपने ग्राफ को स्थापित करने के लिए है। आपके मॉडल को वास्तव में कैसे निष्पादित किया जाता है, इसे व्यवस्थित करने के लिए आपको अतिरिक्त कार्यों की आवश्यकता होगी। प्रत्येक फ़ंक्शन का एक विशिष्ट नाम होगा और सभी घटकों के पास वे कार्य होने चाहिए। किसी घटक के लिए विशिष्ट कुछ भी उस एपीआई के माध्यम से एक समान तरीके से घटक से घटक तक पहुंच योग्य होना चाहिए।

आपका प्रोग्राम इन 'उपयोगकर्ता परिभाषित कार्यों' को कॉल करने का प्रयास नहीं करना चाहिए। इसके बजाय, यह एक सामान्य उद्देश्य 'गणना' फ़ंक्शन या प्रत्येक घटक पर कुछ ऐसा होना चाहिए, और घटक स्वयं उस फ़ंक्शन को कॉल करने और उसके इनपुट को इसके आउटपुट में बदलने का ध्यान रखता है। इनपुट और आउटपुट कनेक्शन उस फ़ंक्शन के सार हैं, यह केवल एक चीज है जिसे प्रोग्राम को देखना चाहिए।

संक्षेप में, इसका छोटा हिस्सा वास्तव में C ++ के लिए विशिष्ट है, लेकिन आपको अपने विशेष समस्या डोमेन के अनुरूप एक प्रकार की रन-टाइम जानकारी लागू करनी होगी। एपीआई द्वारा परिभाषित प्रत्येक फ़ंक्शन के साथ, आपको पता चल जाएगा कि रनटाइम पर कॉल करने के लिए कौन से फ़ंक्शन नाम हैं, और आप उनमें से प्रत्येक कॉल के डेटाटिप्स को जान पाएंगे, और आप इसे प्राप्त करने के लिए नियमित पुराने डायनेमिक लाइब्रेरी लोडिंग का उपयोग करते हैं। यह उचित मात्रा में बॉयलरप्लेट के साथ आएगा, लेकिन यह जीवन का सिर्फ एक हिस्सा है।

एक C ++ विशिष्ट पहलू जिसे आप ध्यान में रखना चाहते हैं, हालांकि आपका API C API होना सबसे अच्छा है, ताकि आप विभिन्न मॉड्यूल के लिए अलग-अलग कंपाइलरों का उपयोग कर सकें, यदि उपयोगकर्ता अपने स्वयं के मॉड्यूल प्रदान कर रहे हैं।

DirectShow एक एपीआई है जो मेरे द्वारा वर्णित सब कुछ करता है और देखने के लिए एक अच्छा उदाहरण हो सकता है।


-2

आप लीडर लाइब्रेरी का उपयोग कर सकते हैं। फिर लाइब्रेरी हेडर के खिलाफ प्रतीकों की जांच करें। यहाँ एक शेल php स्क्रिप्ट है जो https://github.com/comarius/elf_resolver कर रही है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.