ctypes

2009-05-13 13 views
29

के लिए रनटाइम पर LD_LIBRARY_PATH बदलना आप इस पर्यावरण चर को रनटाइम पर कैसे अपडेट करते हैं ताकि ctypes कहीं भी लाइब्रेरी लोड कर सकें? मैंने निम्नलिखित कोशिश की है और न ही काम करने लगते हैं।ctypes

from ctypes import * 
os.environ['LD_LIBRARY_PATH'] = "/home/starlon/Projects/pyCFA635/lib" 
os.putenv('LD_LIBRARY_PATH', "/home/starlon/Projects/pyCFA635/lib") 
lib = CDLL("libevaluator.so") 

उत्तर

35

समय इस तरह के अजगर के रूप में एक कार्यक्रम चल रहा है करके, गतिशील लोडर (ld.so.1 या कुछ इसी तरह) पहले से ही LD_LIBRARY_PATH पढ़ा है और उसके बाद किसी भी बदलाव नहीं दिखाई देगा। इसलिए, जब तक कि पाइथन सॉफ्टवेयर स्वयं LD_LIBRARY_PATH का मूल्यांकन नहीं करता है और dlopen() या पुस्तकालय के संभावित पथ नाम का उपयोग करने के लिए इसका उपयोग करता है, तो स्क्रिप्ट में चर सेट करने का कोई प्रभाव नहीं पड़ेगा।

यह देखते हुए कि आप कहते हैं कि यह काम नहीं करता है, ऐसा लगता है कि पाइथन निर्माण नहीं करता है और सभी संभव लाइब्रेरी नामों को आजमाता है; यह शायद अकेले LD_LIBRARY_PATH पर निर्भर करता है।

+5

यह समस्या का निदान करता है लेकिन इसे हल नहीं करता है। – dbliss

13

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

import os 
path = os.path.dirname(os.path.realpath(__file__)) 
dll = CDLL("%s/iface.so"%path) 

आपके मामले में निम्नलिखित पर्याप्त होना चाहिए।

from ctypes import * 
lib = CDLL("/home/starlon/Projects/pyCFA635/lib/libevaluator.so") 
21

यहां तक ​​कि अगर आप एक पूरी तरह से योग्य पथ CDLL करने के लिए या cdll.LoadLibrary() देते हैं, तो आप अभी भी अजगर लागू करने से पहले LD_LIBRARY_PATH निर्धारित करने की आवश्यकता हो सकती है। यदि आपके द्वारा लोड की गई साझा लाइब्रेरी स्पष्ट रूप से किसी अन्य साझा लाइब्रेरी को संदर्भित करती है और उस लाइब्रेरी के लिए .so में "rpath" सेट नहीं है, तो यह नहीं मिलेगा, भले ही इसे पहले से लोड किया गया हो। लाइब्रेरी में एक आरपीएथ उस लाइब्रेरी

द्वारा आवश्यक अन्य पुस्तकालयों की खोज के लिए उपयोग किए जाने वाले खोज पथ को निर्दिष्ट करता है उदाहरण के लिए, मेरे पास उत्पादित नहीं होने वाले परस्पर निर्भर तृतीय पक्ष पुस्तकालयों के एक सेट का मामला है। बी.एसओ संदर्भ ए.एस.ओ. यहां तक ​​कि अगर मैं पहले से a.so लोड:

ctypes.cdll.LoadLibrary('/abs/path/to/a.so') 
ctypes.cdll.LoadLibrary('/abs/path/to/b.so') 

मैं, क्योंकि b.so बस 'a.so' को संदर्भित करता है दूसरा लोड पर कोई त्रुटि मिलती है, एक rpath बिना, और इसलिए b.so नहीं करता ' टी नहीं जानता कि यह सही है। तो मुझे '/ abs/path/to' शामिल करने के लिए अग्रिम में LD_LIBRARY_PATH सेट करना होगा।

LD_LIBRARY_PATH सेट करने से बचने के लिए, आप .so फ़ाइलों में rpath प्रविष्टि को संशोधित करते हैं। लिनक्स पर, दो उपयोगिताएं मिलीं जो मैंने पाया: chrpath, और patchelf। chrpath उबंटू भंडार से उपलब्ध है। यह rpath को बदल नहीं सकता है। इसलिए यह कभी नहीं था। पैचेलफ अधिक लचीला है।

1

की तरह वर्तमान कार्यशील निर्देशिका करने के लिए एक rpath रिश्तेदार के साथ अपने द्विआधारी संकलित करें:

import os 
os.chdir('/path/to/your/binaries') 

इस तरह:

gcc -shared -o yourbinary.so yoursource.c otherbinary.so \ 
    -Wl,-rpath='.',-rpath='./another/relative/rpath' -fpic 

उसके बाद, आप के साथ कार्यावधि में अजगर में काम निर्देशिका बदलने में सक्षम हैं , लोडर को अन्य बाइनरी जैसे अन्य गतिशील पुस्तकालय भी मिलते हैं।

+0

यह केवल तभी काम करता है जब पुस्तकालय लोड करने की प्रक्रिया की कार्य निर्देशिका लाइब्रेरी की निर्देशिका है। अन्यथा, सापेक्ष रनटाइम पथ निर्भरता को ढूंढने में सक्षम नहीं है, जिसका निर्देशिका लाइब्रेरी से संबंधित है। – danny

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