2016-07-27 19 views
5

मैं संयुक्त रूप से जेएनए का उपयोग कर देशी, गैर थ्रेड-सुरक्षित फोरट्रान लाइब्रेरी को संचालित करने की कोशिश कर रहा हूं। चूंकि लाइब्रेरी थ्रेड-सुरक्षित नहीं है, इसलिए मैं उसी लाइब्रेरी की विभिन्न प्रतियों को तुरंत चालू करने का प्रयास करता हूं, लेकिन स्पष्ट रूप से वे स्मृति पते साझा करना प्रतीत होते हैं। यदि मैं एक पुस्तकालय में एक चर को संशोधित करता हूं, तो दूसरी लाइब्रेरी में चर को संशोधित किया जाता है। यह व्यवहार उन्हें अलग-अलग धागे में एक साथ चलाने के लिए असंभव बनाता है।समान प्रतीकों वाले दो देशी पुस्तकालयों को लोड करते समय मेमोरी समस्याएं

निम्नलिखित कोड उदाहरण दर्शाता है कि मैं क्या मतलब है:

code.f:

subroutine set(var) 
    implicit none 
    integer var,n 
    common/conc/n 
    n=var 
    end subroutine 

    subroutine get(var) 
    implicit none 
    integer var,n 
    common/conc/n 
    var=n 
    end subroutine 

इस फ़ाइल में संकलित किया गया है और की नकल की इस प्रकार है:

gfortran -shared -O2 code.f -o mylib.so -fPIC 
cp mylib.so mylib_copy.so 

तो मैं का उपयोग कर उन दो का उपयोग जेएनए:

import com.sun.jna.Library; 
import com.sun.jna.Native; 
import com.sun.jna.ptr.IntByReference; 

public class JNA { 
    public interface MyLib extends Library { 
     public void set_(IntByReference var); 
     public void get_(IntByReference var); 
    } 

    public static void main(String[] args) { 
     System.setProperty("jna.library.path", "."); 
     MyLib lib = (MyLib) Native.loadLibrary("mylib.so", MyLib.class); 
     MyLib lib_copy = (MyLib) Native.loadLibrary("mylib_copy.so", MyLib.class); 

     # set a common variable in mylib 
     lib.set_(new IntByReference(9)); 

     # access the variable in mylib_copy 
     IntByReference result = new IntByReference(); 
     lib_copy.get_(result); 
     System.out.println(result.getValue()); 

    } 

उपरोक्त कोड का आउटपुट 9 है, जिसका अर्थ है कि दो पुस्तकालय अपनी याददाश्त साझा करते हैं।

क्या उन्हें पूरी तरह से स्वतंत्र बनाने का कोई तरीका है? मैंने इंटेल फोरट्रान कंपाइलर का उपयोग करके भी यही कोशिश की, एक ही परिणाम।

उत्तर

2

जेएनए dlopen के माध्यम से लाइब्रेरी खोलते समय RTLD_LAZY | RTLD_GLOBAL का उपयोग करता है, शायद यही कारण है कि प्रतीकों को साझा किया जा रहा है। आप इस तरह के झंडे को ओवरराइड कर सकते हैं:

int RTLD_LOCAL = ??; // look this up on your system 
Map options = new HashMap(); 
options.put(Library.OPTION_OPEN_FLAGS, RTLD_LOCAL); 
MyLib mylib = Native.loadLibrary("mylib", MyLib.class, options); 
MyLib mylib2 = Native.loadLibrary("mylib2", MyLib.class, options); 
+0

मैं rtld_local कैसे ढूंढ सकता हूं? मैं CentOS 7 –

+0

का उपयोग कर रहा हूं मुझे 'RTLD_LOCAL = 1' सेट करने के साथ अपेक्षित व्यवहार मिलता है, हालांकि मुझे लगता है कि 'RTLD_LOCAL' का मूल्य 0 (GLIBC2.4) है। यदि मैंने 'RTLD_LOCAL = 0' सेट किया है, तो' Native.loadLibrary' शिकायत करता है कि लाइब्रेरी (यानी फ़ाइल) नहीं मिल सकती है। पीएस: आपके उत्तर में हस्ताक्षर के साथ ऐसी कोई विधि 'मूल .loadLibrary' नहीं है, आप इंटरफ़ेस क्लास खो रहे हैं। –

+0

आपको 'RTLD_LAZY'' शामिल करना पड़ सकता है (जिसमें ओएसएक्स पर "1" का मान है, लिनक्स एटीएम की जांच नहीं कर सकता)। 'RTLD_LOCAL' को" 1 "के रूप में परिभाषित न करें, यह गलत है। 'विकल्प = 1' को परिभाषित करने और इसे छोड़ने के साथ कुछ भी गलत नहीं है; स्थिरांक को परिभाषित करने की कोई आवश्यकता नहीं है यदि कोई भी कोड के उस हिस्से का पुन: उपयोग नहीं करेगा। – technomage

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