2011-06-15 21 views
12

सुबह!एंड्रॉइड एनडीके आयात-मॉड्यूल/कोड पुन: उपयोग

मैंने एक छोटी एनडीके परियोजना बनाई है जो जावा और सी ++ के बीच जेएनआई के माध्यम से वस्तुओं के गतिशील क्रमिकरण की अनुमति देता है। तर्क इस तरह काम करता है:

बीन -> JavaCInterface.Java -> JavaCInterface.cpp -> JavaCInterface.java -> बीन

समस्या मैं अन्य परियोजनाओं में इस कार्यक्षमता का उपयोग करना चाहते हैं। मैंने प्रोजेक्ट से टेस्ट कोड अलग किया और एक "परीक्षक" प्रोजेक्ट बनाया। परीक्षक प्रोजेक्ट जावा ऑब्जेक्ट को सी ++ के माध्यम से भेजता है जो उसके बाद जावा परत पर गूंजता है।

मैं जोड़ने सोचा होगा बहुत सरल हो - ("सरल" NDK/JNI के मामले में किया जाता है आमतौर पर हताशा का एक दिन) मैं एक स्रोत परियोजना के रूप में JNIBridge परियोजना जोड़ा गया है और Android.mk को निम्नलिखित लाइनों सहित:

NDK_MODULE_PATH=.../JNIBridge/jni/"

JNIBridge/JNI/JavaCInterface/Android.mk:

... 
include $(BUILD_STATIC_LIBRARY) 

JNITester/JNI/Android.mk:

... 
include $(BUILD_SHARED_LIBRARY) 
$(call import-module, JavaCInterface) 

यह सब ठीक काम करता है। JavaCInterface मॉड्यूल से हेडर पर भरोसा करने वाली सी ++ फ़ाइलें ठीक काम करती हैं। इसके अलावा जावा कक्षाएं खुशी से जेएनआई ब्रिज परियोजना से इंटरफेस का उपयोग कर सकती हैं। सभी लिंकिंग खुश है।

दुर्भाग्य से JavaCInterface.java जिसमें देशी विधि कॉल शामिल हैं, स्थिर पुस्तकालय में स्थित जेएनआई विधि नहीं देख सकते हैं। (तर्कसंगत रूप से वे एक ही प्रोजेक्ट में हैं लेकिन दोनों परियोजना में आयात किए जाते हैं जहां आप उपर्युक्त तंत्र के माध्यम से उनका उपयोग करना चाहते हैं)।

मेरे वर्तमान समाधान निम्नानुसार हैं। मैं आशा करती हूं किसी को कुछ है कि मैं क्या हासिल करने की कोशिश कर रहा हूँ की मॉड्यूलर प्रकृति को सुरक्षित करेगा कर सकते हैं सुझाव:


मेरे वर्तमान समाधान तो जैसे बुला परियोजना में JavaCInterface सीपीपी फ़ाइलों को शामिल करने होगा:

LOCAL_SRC_FILES := FunctionTable.cpp $(PATH_TO_SHARED_PROJECT)/JavaCInterface.cpp 

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


मैं प्रत्येक स्थानीय परियोजना जो तब आयातित मॉड्यूल से जोड़ने में JNI विधि हस्ताक्षर का एक नया सेट बना सकते हैं। फिर, यह कार्यान्वयन बहुत कसकर बांधता है।

उत्तर

14

रक्त के पसीने और आंसुओं के बाद मैंने इसे समझ लिया है।

  • एंड्रॉइड जेएनआई केवल अपनी बाइनरी को SHARED_LIBRARY से लोड करता है।
  • जेएनआई भारित साझा लाइब्रेरी से उचित विधि हस्ताक्षर/स्टब्स को देशी कॉल को आजमाएगा और लिंक करेगा (यह लिंक किए गए साझा पुस्तकालयों के अंदर नहीं दिखेगा)।
  • आप इन विधियों के साथ एक स्टेटिक लाइब्रेरी बना सकते हैं और इसे अपने एप्लिकेशन द्वारा उपयोग की जाने वाली साझा लाइब्रेरी में बना सकते हैं।

आप अपने Andriod.xml में निम्नलिखित कोड का उपयोग कर अपने मूल परियोजना में अपनी स्थिर पुस्तकालय का निर्माण कर सकते हैं:

include $(CLEAR_VARS) 
LOCAL_CFLAGS := -O0 
LOCAL_MODULE := LibraryToBeUsedInsideSharedLib 
LOCAL_SRC_FILES := ... 
include $(BUILD_STATIC_LIBRARY) // This builds a "Static Object" here: 
           // /Project/obj/local/armeabi/libLibraryToBeUsedInsideSharedLib.a 

include $(CLEAR_VARS) 
LOCAL_MODULE  := LibraryCalledFromJava 
LOCAL_SRC_FILES := ... 
LOCAL_STATIC_LIBRARIES := LibraryToBeUsedInsideSharedLib 
include $(BUILD_SHARED_LIBRARY) 

LOCAL_STATIC_LIBRARIES आपकी साझा लाइब्रेरी में स्टेटिक लाइब्रेरी भी शामिल है। अपने जावा कोड में आप अब इस कॉल कर सकते हैं:

System.loadLibrary("LibraryCalledFromJava"); 

आप किसी भी देशी अपने जावा कोड में किसी भी बिंदु से LibraryToBeUsedInsideSharedLib पुस्तकालय के अंदर स्थित तरीकों कॉल करने के लिए सक्षम होना चाहिए।

आप libLibraryToBeUsedInsideSharedLib.a फ़ाइल निर्यात और अन्य परियोजनाओं में उपयोग कर सकते हैं बाहरी परियोजना की Android.xml को यह जोड़कर:

include $(CLEAR_VARS) 
LOCAL_MODULE   := LibraryToBeUsedInsideSharedLib 
LOCAL_LDLIBS   := -llog/ 
LOCAL_SRC_FILES   := $(MY_PREBUILT_LIB_DIR)/libLibraryToBeUsedInsideSharedLib.a 
include $(PREBUILT_STATIC_LIBRARY) 
संबंधित मुद्दे