2013-10-17 6 views
19

मैं अपने स्वयं के जेनी स्रोत लिखने की कोशिश कर रहा हूं। कुछ NDK नमूने को देखते हुए, मैंने पाया कि वे अक्सर इसएंड्रॉइड एनडीके में जेएनआईएक्सपोर्ट और जेएनआईसीएएल का उपयोग कब करें?

JNIEXPORT void JNICALL Java_com_example_plasma_PlasmaView_renderPlasma(JNIEnv * env, jobject obj, jobject bitmap, jlong time_ms)

की तरह उन मैक्रो JNIEXPORT और JNICALL जावा पैकेज के नाम से follewed का उपयोग मैं इसे googled लेकिन मैं नहीं समझ सकता कि कब और कैसे इन उपयोग करने के लिए मैक्रोज़

उत्तर

23

JNIEXPORT और JNICALL NDK_ROOT में परिभाषित कर रहे हैं। आपके सेटअप के आधार पर यह पथ अलग होगा, लेकिन अधिकतर समान होगा।

#define JNIIMPORT 
#define JNIEXPORT __attribute__ ((visibility ("default"))) 
#define JNICALL 

जेएनआईएक्सपोर्ट का निर्माण देशी बाइनरी (* .so फ़ाइल) की गतिशील तालिका में देशी कार्यों को करने के लिए किया जाता है। उन्हें "छुपा" या "डिफ़ॉल्ट" पर सेट किया जा सकता है (अधिक जानकारी here)। यदि ये फ़ंक्शंस गतिशील तालिका में नहीं हैं, तो जेएनआई उन्हें कॉल करने के लिए फ़ंक्शंस नहीं ढूंढ पाएगा, इसलिए रजिस्टरनेट्स कॉल रनटाइम पर विफल हो जाएगी।

इसलिए किसी को भी काफी आसानी से अपने मूल कोड डिकंपाइल सकता है यह देखते हुए कि सभी कार्यों डिफ़ॉल्ट रूप से गतिशील तालिका में समाप्त हो सकता है। जेएनआई को इसे ढूंढने की जरूरत होने पर हर फंक्शन कॉल बाइनरी में बनाया जाता है। इसे संकलक विकल्प -fvisibility का उपयोग करके बदला जा सकता है। मैं अनुशंसा करता हूं कि प्रत्येक व्यक्ति आपके कोड को सुरक्षित रखने के लिए इसे -fvisibility=hidden पर सेट करें, और फिर बाह्य दृश्यता के रूप में कार्यों को ध्वजांकित करने के लिए जेएनआईएक्सपोर्ट का उपयोग करें।

स्ट्रिप कमांड का उपयोग केवल डीबग प्रतीकों को हटा देता है, गतिशील तालिका अलग होती है। Objdump के साथ एक नाटक है यह देखने के लिए कि कोई व्यक्ति आपकी .so फ़ाइलों से कितना बाहर निकल सकता है।

हम हाल ही में इस तक पहुंचे हैं, उम्मीद है कि इससे किसी की मदद मिलेगी।

संपादित करें: हम एक कस्टम बिल्ड सिस्टम का उपयोग करते हैं, इसलिए दृश्यता विकल्प अन्य बिल्ड सेटअप के लिए डिफ़ॉल्ट रूप से सेट किया जा सकता है। अधिक जानकारी this SO answer में उपलब्ध है।

+0

जेएनआईसीओएल का क्या अर्थ है? – Lealo

+1

जेएनआईसीएएल एंड्रॉइड (उपर्युक्त के रूप में) पर एक खाली परिभाषा है लेकिन यह मंच अनुकूलता के लिए है। विंडोज़ जेडीके पर जेएनआईसीओएल को '__stdcall' (https://msdn.microsoft.com/en-us/library/zxk0tw93.aspx) के रूप में परिभाषित किया गया है। –

0

बस अपने मूल वर्गों पर 'जावा' चलाएं और जो कुछ भी उत्पन्न करता है उसका उपयोग करें। जब आपके पास ऐसा उपकरण होता है जो आपको 100% विश्वसनीयता के साथ उत्पन्न कर सकता है तो आपको इसके अंदरूनी और बहिष्कार जानने की आवश्यकता नहीं है।

+0

मुझे इस आदेश के बारे में कोई जानकारी नहीं है। मैं एनएनडी-बिल्ड से पहले इसका इस्तेमाल करता हूं? – nawara

+0

मेरे पास एनएनके-बिल्ड के बारे में कोई विचार नहीं है, लेकिन मैं 15 साल से जेएनआई कर रहा हूं, और मैं कहीं भी जाव और जाव के बिना नहीं जाऊंगा। आप इसे हमेशा देख सकते हैं। – EJP

4

आप अपने JNI की मशीन निर्भर हिस्से में उन मैक्रो की परिभाषा पा सकते हैं ($JAVA_HOME/include/<arch>/jni-md.h में आमतौर पर) शामिल हैं।

संक्षेप में, JNIEXPORT किसी भी संकलक सुनिश्चित करना है कि यह देखते हुए ठीक तरह से कार्य निर्यात किया जाता है के लिए आवश्यक निर्देशों में शामिल है। एंड्रॉइड (और अन्य लिनक्स-आधारित सिस्टम) पर, जो खाली हो जाएगा।

JNICALL किसी भी संकलक सुनिश्चित करना है कि यह देखते हुए समारोह उचित बुला सम्मेलन के साथ व्यवहार किया जाता है के लिए आवश्यक निर्देशों में शामिल है। शायद एंड्रॉइड पर भी खाली है (यह w32 पर __stdcall है)।

सामान्य तौर पर, आप उन्हें में छोड़ देना चाहिए, भले ही वे खाली #define रों रहे हैं।/प्लेटफार्मों/एंड्रॉयड-9/कट्टर हाथ/usr/शामिल/jni.h

+1

एंड्रॉइड पर कुछ आर्किटेक्चर पर जेएनआईसीओएल खाली नहीं है। जेएनआईसीएएलएल हमेशा इस्तेमाल किया जाना चाहिए। JNIEXPORT का उपयोग तब किया जाना चाहिए यदि आप फ़ंक्शंस के परिवार के परिवार का उपयोग नहीं कर रहे हैं। –

0

सरल शब्दों में:

  • JNIEXPORT अगर आप कार्यों की registerNatives परिवार का उपयोग करना चाहिए तो आप JNIEXPORT उपयोग नहीं करना चाहिए। अन्यथा आपको इसका इस्तेमाल करना होगा।
  • JNICALL हमेशा इस्तेमाल किया जाना चाहिए।

जेएनआईएक्सपोर्ट यह सुनिश्चित करता है कि फ़ंक्शन प्रतीक तालिका में दिखाई दे। जेएनआईसीएएलएल सुनिश्चित करता है कि फ़ंक्शन सही कॉलिंग सम्मेलन का उपयोग करता है। एंड्रॉइड जेएनआईसीओएल पर आर्किटेक्चर के आधार पर एक अलग मूल्य है। एआरएम खाली है जो आपको इसे शामिल करने के लिए चाल नहीं कर सकता है। लेकिन आपको जेएनआईसीओएल का उपयोग करना होगा।

registerNatives आपको JNI_onLoad पर या भविष्य में कभी-कभी फ़ंक्शन को प्रोग्रामेटिक रूप से लिंक करने की अनुमति देता है। registerNatives पहले गलत फ़ंक्शन नामों को पकड़ने की अनुमति देता है और मैं इस मार्ग की अनुशंसा करता हूं।

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