जब मैं इस विषय की बात करता हूं तो मैं थोड़ा "क्षतिग्रस्त सामान" हूं। मैं एम्बेडेड टेलीकॉम के लिए काफी बड़े एपीआई डिजाइन और रखरखाव करता था। एक संदर्भ जहां आप कुछ भी नहीं ले सकते हैं। वैश्विक चर या टीएलएस जैसी चीजें भी नहीं। कभी-कभी ढेर बफर भी दिखाते हैं कि वास्तव में रॉम मेमोरी को संबोधित किया जाता है।
इसलिए, यदि आप "सबसे कम आम denominator" की तलाश में हैं, तो आप यह भी सोचना चाहेंगे कि आपके लक्षित माहौल में कौन सी भाषा संरचनाएं उपलब्ध हैं (संकलक मानक सी के भीतर कुछ भी स्वीकार करने की संभावना है, लेकिन अगर कुछ असमर्थित है लिंकर नहीं कहेंगे)।
यह कहकर कि, मैं हमेशा वैकल्पिक 1 के लिए जाऊंगा। आंशिक रूप से क्योंकि (जैसा कि अन्य ने बताया है), आपको सीधे उपयोगकर्ता के लिए स्मृति आवंटित नहीं करना चाहिए (एक अप्रत्यक्ष दृष्टिकोण आगे बताया गया है)। भले ही उपयोगकर्ता को शुद्ध और सादे सी के साथ काम करने की गारंटी दी जाती है, फिर भी वे लीक, डायग्नोस्टिक लॉगिंग आदि को ट्रैक करने के लिए अपने स्वयं के अनुकूलित मेमोरी प्रबंधन API का उपयोग कर सकते हैं। इस तरह की रणनीतियों के लिए समर्थन की सराहना की जाती है।
त्रुटि संचार एपीआई से निपटने के दौरान सबसे महत्वपूर्ण चीजों में से एक है। चूंकि उपयोगकर्ता के पास उसके कोड में त्रुटियों को संभालने के लिए अलग-अलग तरीके हैं, इसलिए आपको पूरे एपीआई में इस संचार के बारे में जितना संभव हो सके उतना संगत होना चाहिए। उपयोगकर्ता आपके एपीआई की तरफ एक सतत तरीके से और न्यूनतम कोड के साथ त्रुटि प्रबंधन को लपेटने में सक्षम होना चाहिए। मैं आमतौर पर हमेशा स्पष्ट enum कोड या परिभाषित/typedefs का उपयोग करने की सिफारिश करेंगे। मैं व्यक्तिगत रूप से typedef पसंद करते हैं: एड enums:
typedef enum {
RESULT_ONE,
RESULT_TWO
} RESULT;
..because इसे टाइप/असाइनमेंट सुरक्षा प्रदान करता है।
होने के बाद-अंतिम त्रुटि फ़ंक्शन भी अच्छा है (केंद्रीय भंडारण की आवश्यकता है), मैं व्यक्तिगत रूप से इसे पहले से ही मान्यता प्राप्त त्रुटि के बारे में अतिरिक्त जानकारी प्रदान करने के लिए पूरी तरह से उपयोग करता हूं।बेहतर
struct Buffer
{
unsigned long size;
char* data;
};
फिर अपने एपीआई दिख सकता है::
ERROR_CODE func(params... , Buffer* outBuffer);
यह रणनीति भी अधिक विस्तृत के लिए खुल जाता है
शब्दाडंबर विकल्प 1 का इस तरह सरल यौगिकों बनाकर सीमित किया जा सकता तंत्र। उदाहरण के लिए मान लीजिए कि आप (यदि आप बफर आकार बदलना होगा जैसे) उपयोगकर्ता के लिए स्मृति को आबंटित करने में सक्षम होना चाहिए, तो आप इस के लिए एक परोक्ष दृष्टिकोण प्रदान कर सकते हैं:
struct Buffer
{
unsigned long size;
char* data;
void* (*allocator_callback)(unsigned long size);
void (*free_callback)(void* p);
};
बेशक, इस तरह के निर्माणों की शैली हमेशा होता है गंभीर बहस के लिए खुला
शुभकामनाएं!
बफर का प्रकार char ** नहीं होना चाहिए? इसके अलावा, आपको विकल्प में एक buffer_size क्यों चाहिए और विकल्प दो में नहीं? – mweerden
वह पैरामीटर के रूप में एक प्रीलाक्टेड बफर पास करता है और कॉल किए गए फ़ंक्शन को त्रुटि टेक्स्ट से भरने की अपेक्षा करता है। – sharptooth
ठीक है, लेकिन फिर buffer_size को पॉइंटर होने की आवश्यकता नहीं है, है ना? – mweerden