2011-03-24 12 views
5

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

ext1 < - ext2 < - आंतरिक

अर्थात आंतरिक बाहरी पुस्तकालय ext2 का उपयोग करता है जो फिर से बाहरी पुस्तकालय ext1 का उपयोग करता है। मैंने जो कोशिश की है वह है:

System.loadLibrary("ext1"); 
System.loadLibrary("ext2"); 
NativeLIbrary.loadLibrary("internal",xxx.class); 

यह दृष्टिकोण "ext2" लाइब्रेरी लोड करते समय "अनसुलझा अपवाद" के साथ विफल रहता है; लिंकर प्रतीकों के बारे में शिकायत करता है जो वास्तव में पुस्तकालय "ext1" में मौजूद हैं। तो यह semmes कि System.loadLibrary() फ़ंक्शन वैश्विक रूप से उपलब्ध "ext1" से प्रतीकों को नहीं बनाता है? stdlib समारोह dlopen() के रूप में उपयोग करते समय:

handle = dlopen(lib_name , RTLD_GLOBAL); 

सभी प्रतीकों @lib_name में पाया अनुवर्ती लोड में प्रतीक समाधान के लिए उपलब्ध हो जाएगा; मुझे लगता है कि मैं जावा विविधता System.loadLibrary() के लिए कुछ ऐसा करना चाहता था?

सादर - Joakim होव

+0

पुस्तकालयों जावा संपत्ति 'java.library.path' में परिभाषित करने के लिए पथ है? –

+0

अच्छी तरह से - पुस्तकालयों का पता लगाना वास्तव में एक और गड़बड़ी है, और मैंने System.load (full_path_to_shared_library) का उपयोग करने का सहारा लिया है - लेकिन मुझे लगता है कि समस्या यह है कि ज्यादातर नेटबीन समस्या है। पुस्तकालय "ext" लोड करते समय अपवाद प्रतीक समाधान चरण के दौरान होता है, यानी लाइब्रेरी सही ढंग से स्थित है और इसी तरह। मुझे लगता है कि यह डर है कि यह निम्न स्तर dlopen() रनटाइम में गहरे नीचे कॉल में RTLD_GLOBAL ध्वज (या इसकी कमी) से संबंधित है। – user422005

उत्तर

2

ठीक है;

मुझे अंत में एक स्वीकार्य समाधान मिला है, लेकिन बिना भारी मात्रा में हुप्स। मैं क्या करता हूं

  1. गतिशील लिंकिंग लाइब्रेरी (libdl.so) से dlopen() फ़ंक्शन को मैप करने के लिए सामान्य जेएनए तंत्र का उपयोग करें।
  2. RTLD_GLOBAL सेट विकल्प के साथ बाहरी पुस्तकालयों "ext1" और "ext2" को लोड करने के लिए जेएनए के साथ मैप किए गए dlopen() फ़ंक्शन का उपयोग करें।

यह वास्तव में :-)

0

इस प्रयास करें, अपने कोड को यह समारोह जोड़ें। अपने डीएलएस लोड करने से पहले इसे कॉल करें। पैरामीटर के लिए, अपने डीएलएस के स्थान का उपयोग करें।

 

    public boolean addDllLocationToPath(String dllLocation) 
    { 
     try 
     { 
      System.setProperty("java.library.path", System.getProperty("java.library.path") + ";" + dllLocation); 
      Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); 
      fieldSysPath.setAccessible(true); 
      fieldSysPath.set(null, null); 
     } 
     catch (Exception e) 
     { 
      System.err.println("Could not modify path"); 
      return false; 
     } 
     return true; 
    } 
} 
 
+1

प्रयास के लिए धन्यवाद - पुस्तकालयों को ढूंढने की बात आने पर आपका सुझाव अच्छी तरह से काम करता है। लेकिन दुर्भाग्य से मेरी समस्या नहीं है, समस्या यह है कि लाइब्रेरी "ext2" में प्रतीकों को "ext1" में फ़ंक्शंस के लिए उपलब्ध नहीं है - जब dlopen() लाइब्रेरी कॉल का उपयोग करते समय सीधे (शायद यही मुझे करना चाहिए ???) यह व्यवहार एक पूर्णांक ध्वज द्वारा नियंत्रित होता है, और जिस व्यवहार को मैं चाहता हूं वह RTLD_GLOBAL ध्वज के साथ प्राप्त किया जाता है। ऐसा लगता है कि यह सोचा से ज्यादा कठिन लग रहा था ?! – user422005

2

यह एक पुराने सवाल है काम करने के लिए लगता है, लेकिन मैं एक स्वीकार्य समाधान है, जो भी पोर्टेबल होना चाहिए मिल गया है, और मैंने सोचा कि मैं एक उत्तर पोस्ट करना चाहिए। समाधान JNA के NativeLibrary#getInstance() का उपयोग करना है, क्योंकि लिनक्स पर यह RTLD_GLOBAL से dlopen() (और विंडोज़ पर इसकी आवश्यकता नहीं है) पास होगा।

अब, अगर आप इस पुस्तकालय का उपयोग कर रहे एक जावा native विधि लागू करने के लिए, आप भी एक ही पुस्तकालय पर System.load() (या Sysem.loadLibrary()) कॉल करने के लिए, NativeLibrary#getInstance() बुला के बाद की आवश्यकता होगी।

सबसे पहले, एक JNA बग के लिए एक लिंक: JNA-61

वहाँ में एक टिप्पणी का कहना है कि मूल रूप से एक निर्भरता लोड करना चाहिए वास्तविक पुस्तकालय JNA, नहीं मानक जावा जिस तरह से भीतर से उपयोग करने के लिए पहले।

String libPath = 
     "/path/to/my/lib:" + // My library file 
     "/usr/local/lib:" + // Libraries lept and tesseract 
     System.getProperty("java.library.path"); 

System.setProperty("jna.library.path", libPath); 

NativeLibrary.getInstance("lept"); 
NativeLibrary.getInstance("tesseract"); 
OcrTesseractInterf ocrInstance = (OcrTesseractInterf) 
     Native.loadLibrary(OcrTesseractInterf.JNA_LIBRARY_NAME, OcrTesseractInterf.class); 

मैं Tesseract उपयोग करते हुए मेरे जावा अनुप्रयोग के लिए ओसीआर क्षमता प्रदान करने के लिए एक छोटा सा पुस्तकालय लिखा है: मैं हूँ बस अपना कोड को कॉपी-पेस्ट, यह एक विशिष्ट परिदृश्य है।टेस्सेरैक्ट लेप्टनिका पर निर्भर करता है, इसलिए मेरी लाइब्रेरी का उपयोग करने के लिए, मुझे लाइब्रेरी लेप्ट और टेसरेक्ट पहले लोड करने की आवश्यकता है। मानक माध्यमों के साथ पुस्तकालयों को लोड करना (System.load() और System.loadLibrary()) चाल नहीं करता है, न ही गुणों को सेट करता है jna.library.path या java.library.path। जाहिर है, जेएनए पुस्तकालयों को अपने तरीके से लोड करना पसंद करता है।

यह लिनक्स में मेरे लिए काम करता है, मुझे लगता है कि अगर कोई उचित लाइब्रेरी पथ सेट करता है, तो यह अन्य ओएस में भी काम करना चाहिए।

1

इसके लिए अभी तक एक और समाधान है। आप सीधे JNI कोड अंदर dlopen कर सकते हैं, इस तरह:

void loadLibrary() { 
    if(handle == NULL) { 
    handle = dlopen("libname.so", RTLD_LAZY | RTLD_GLOBAL); 
    if (!handle) { 
     fprintf(stderr, "%s\n", dlerror()); 
     exit(EXIT_FAILURE); 
    } 
    } 
} 

... 
... 

loadLibrary(); 

इस तरह, आप RTLD_GLOBAL साथ पुस्तकालय खुल जाएगा।

आप यहाँ विस्तृत वर्णन पा सकते हैं: http://www.owsiak.org/?p=3640

+0

धन्यवाद, मैं घंटों के लिए इस समस्या पर था और उपर्युक्त समाधानों में से कोई भी – dargaud

+0

काम नहीं करता था। ओओओ। धन्यवाद;)। ओओओ। – mko

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