जब तक आपको थ्रेड सुरक्षा की आवश्यकता नहीं है, यह मुश्किल नहीं है। आपको लाइब्रेरी के इंटरफ़ेस के साथ एक निजी (स्थैतिक) हैंडलर प्रदान करना होगा जो लाइब्रेरी डेटा स्ट्रक्चर को आपके लिपटे संस्करण में बदल देता है, फिर उसके कॉलबैक को तर्क के रूप में कॉल करता है। आपका इंटरफेस तरह दिखेगा:
// wrapped_foo_lib.h
typedef struct { ... } NewDataFormat;
typedef void (*WRAPPED_CALLBACK)(NewDataFormat);
void wrappedFooLibCall(int x, char c, WRAPPED_CALLBACK cb);
आपका कार्यान्वयन, जो ग्राहक को देखने के लिए हो जाता है कभी नहीं है:
// wrapped_foo_lib.c
// This static var makes this module _not_ thread safe.
static WRAPPED_CALLBACK wrapped_callback;
static void private_handler(DataFormat data) {
NewDataFormat new_data = ...; // extract new_data from data
wrapped_callback(new_data);
}
void wrappedFooLibCall(int x, char c, WRAPPED_CALLBACK cb) {
wrapped_callback = cb;
foo_lib(x, c, private_handler);
}
गैर धागा सुरक्षा कारण है कि हर API कॉलबैक एक void *
कि आप शामिल होना चाहिए परिभाषित करने के लिए, जो कॉलबैक पर भेजा जाता है। अर्थात। अपने तरीके से सुसज्जित पुस्तकालय अब जब आप fooLib
कहते हैं, आप बिल्कुल env
रूप में किसी भी struct प्रस्तुत के रूप में
fooLib(int, char, void (*)(DataFormat, void *env));
void handler(DataFormat, void *env);
परिभाषित किया जाना चाहिए, और इसे वापस आप के लिए पारित किया है। इस तरह से आप आवरण में स्थिर चर के साथ बांटना कर सकते हैं:
// wrapped_foo_lib.c
typedef struct { WRAPPED_CALLBACK wrapped_callback; } ENV;
static void private_handler(DataFormat data, void *void_env) {
ENV *env = (ENV*)void_env;
NewDataFormat new_data = ...; // extract new_data from data
env->wrapped_callback(new_data);
}
void wrappedFooLibCall(int x, char c, WRAPPED_CALLBACK cb) {
ENV env[1] = {{ cb }};
foo_lib(x, c, env);
}
यह धागा सुरक्षित क्योंकि ENV
आवंटित ढेर कर रहा है। इस अच्छा प्रदर्शन का एक अच्छा उदाहरण libpng है।
सी 9 0 को अधिक आधुनिक वाक्यविन्यास में अपडेट करने के लिए स्वतंत्र महसूस करें।
कभी-कभी कॉलबैक पंजीकरण फ़ंक्शन पॉइंटर के अतिरिक्त 'शून्य *' स्वीकार करेगा, और उसके बाद कॉलबैक फ़ंक्शन में 'शून्य *' पास करेगा। यह कस्टम डेटा को फ़ंक्शन पॉइंटर से "संलग्न" होने की अनुमति देता है। उस सुविधा के बिना, यह बहुत मुश्किल है। –
यह सच है, लेकिन यह पुस्तकालय कोई शून्य * सूचक नहीं लेता है। – Saaras
यह थोड़ा अस्पष्ट है कि सभी बिट्स एक साथ कैसे फिट होते हैं। 'FooLib' का उपयोग कैसे किया जाता है? पुस्तकालय कैसे '/ हैंडलर' का आह्वान करता है? क्लाइंट कोड आपके रैपर का उपयोग कैसे करता है - आपने केवल इतना कहा है कि रैपर में 'हैंडलर नया' फ़ंक्शन है लेकिन इसका अर्थ यह है कि इसे लाइब्रेरी द्वारा कॉल किया जाता है, न कि क्लाइंट कोड। तो क्लाइंट कोड क्या करता है - मूल पुस्तकालय या आपका रैपर? – kaylum