Android NDK C ++ JNI (मूल के लिए कोई कार्यान्वयन नहीं मिला ...)


86

मैं सी ++ के साथ एनडीके का उपयोग करने की कोशिश कर रहा हूं और विधि नामकरण सम्मेलन को सही नहीं कर सकता। मेरी मूल विधि इस प्रकार है:

extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
   //
}
}

एक हेडर के साथ "C" {} astern में लिपटे हुए।

सब कुछ ठीक संकलित करता है, एक .so फ़ाइल बनाता है और मेरी परियोजना के तहत libs फ़ोल्डर में कॉपी करता है, लेकिन जब मैं डीबग और रन करता हूं तो मुझे एक लॉग कैट संदेश मिलता है कि "मूल के लिए कोई कार्यान्वयन नहीं मिला ..."। क्या ऐसा कुछ है जो एनडीके के सभी उदाहरणों के सी में गायब हैं?

धन्यवाद।


क्या आप अपने जेएनआई स्टब्स का इस्तेमाल कर रहे हैं javah? अगर नहीं, तो भी आपको करना चाहिए। :-P
क्रिस जस्टर-यंग

7
सबसे अधिक संभावना है क्योंकि आपने फोन नहीं किया थाSystem.loadLibrary
इगोरगानपोलस्की

1
आपके सवाल के लिए धन्यवाद। मैंने आज एक नई चीज सीखी।
शेडी मोहम्मद शेरिफ

जवाबों:


148

कुछ चीजें हैं जो "कोई कार्यान्वयन नहीं मिला" के लिए नेतृत्व कर सकती हैं। एक फ़ंक्शन प्रोटोटाइप नाम गलत हो रहा है, दूसरा बिल्कुल भी .so लोड करने में विफल हो रहा है। क्या तुम आश्वस्त हो किSystem.loadLibrary() विधि का उपयोग करने से पहले बुलाया जा रहा है?

यदि आपके पास कोई JNI_OnLoadफ़ंक्शन परिभाषित नहीं है , तो आप एक बनाना चाहते हैं और इसे लॉग संदेश को केवल यह सत्यापित करने के लिए छोड़ दिया है कि लिब को सफलतापूर्वक खींचा जा रहा है।

आपने पहले से ही सबसे आम समस्या को चकमा दिया extern "C"- उपयोग करना भूल गए - इसलिए यह या तो ऊपर या कुछ मामूली गलत वर्तनी है। जावा घोषणापत्र कैसा दिखता है?


13
यीशु! आपने मुझे काम के लायक घंटों की बचत की - यह पढ़ने के बाद मुझे याद आया कि मैंने अपने लोड-कॉल को कॉल किया था ...
zeboidlund

11
आपने मुझे भी बचा लिया! मैंने अपने फ़ंक्शन का नाम और अन्य चीजों की एक जोड़ी को चौगुनी जाँच की ... लेकिन मैं "C" को भूल गया, और इसे प्रश्न में नोटिस भी नहीं किया!
क्वर्टी

1
अब Android डॉक्स साइट पर: developer.android.com/training/articles/perf-jni.html#faq_ULE
fadden

2
एक ऐसा मामला भी है जिसके बारे में किसी ने नहीं बताया: आप फ़ंक्शन नामों में '_' (अंडरस्कोर) का उपयोग नहीं कर सकते क्योंकि अंडरस्कोर पैकेज सेपरेटर के रूप में नजरअंदाज कर रहे हैं। तो, केवल ऊंट मामले के कार्य के नाम संभव हैं
नूलिक

2
@ नलिक: यदि आप "_1" के रूप में बच जाते हैं तो '_' का उपयोग कर सकते हैं ।
फादन

18

इस त्रुटि के लिए एक अतिरिक्त कारण: आपके अनिर्दिष्ट देशी विधि नाम में अंडरस्कोर नहीं होना चाहिए!

उदाहरण के लिए, मैं नाम के एक C फ़ंक्शन को निर्यात करना चाहता था AudioCapture_Ping()। यहाँ C में मेरा निर्यात घोषणा है:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object);  //Notice the underscore before Ping

यहाँ मेरा जावा क्लास फंक्शन आयात कर रहा था:

package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
    private native int AudioCapture_Ping();  // FAILS
    ...

जब तक मैंने अंडरस्कोर नहीं हटाया, मुझे अपने देशी तरीके से गतिशील रूप से लिंक करने के लिए एंड्रॉइड नहीं मिला:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapturePing(JNIEnv *pJniEnv, jobject object); 

package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
    private native int AudioCapturePing();  // THIS WORKS!
    ...

5
जावा-भाषा घोषणा में '_' की घटनाओं को मूल घोषणा में "_1" से प्रतिस्थापित किया जाना चाहिए। Docs.oracle.com/javase/7/docs/technotes/guides/jni/sp// पर तालिका 2-1 देखें ।
फादन

1
इतना स्पष्ट है, फिर भी मैंने डिबगिंग के कई घंटों के बाद इसे अपने आप निकालने का प्रबंधन नहीं किया ... धन्यवाद, आपने मुझे बचा लिया!
जॉर्ज एटसेव

@ user1222021 मेरा एक प्रश्न है, क्या हम परियोजना में सभी गतिविधियों के लिए cpp विधि निर्यात कर सकते हैं, क्या हमें .cpp फ़ाइल में विधि में गतिविधि का नाम निर्दिष्ट करने की आवश्यकता है?
बालफ्लियर

14

मुझे भी यही समस्या थी, लेकिन मेरे लिए त्रुटि Android.mk फ़ाइल में थी। मैंने लिया:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp 

लेकिन यह होना चाहिए:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp 

नोट + के बजाय विस्तार = : =

मुझे आशा है कि वह मदद करेंगे।


2
या आप बस उन सभी को एक लाइन पर जोड़ सकते हैं, या `\ 'लाइन ब्रेक चरित्र का उपयोग कर सकते हैं।
इगोरगानापोलस्की

6

एक्सटर्नल "C" को स्वचालित रूप से जेनरेट किए गए स्टूडियो उदाहरण में प्रदान किया गया है, लेकिन {} कोष्ठक में, निम्नलिखित कार्यों सहित फ़ाइल के बाकी हिस्सों को लपेटना भूल गया। केवल पहले समारोह में काम किया।


4

एक अतिरिक्त कारण: android.mk में LOCAL_STATIC_LIBRARIES के बजाय LOCAL_WHOLE_STATIC_LIBRARIES का उपयोग करें। यह अप्रयुक्त एपीआई कॉल को बाहर करने से पुस्तकालय को रोकता है क्योंकि NDK जावा कोड से देशी बाइंडिंग के उपयोग का पता नहीं लगा सकता है।


1
इसमें कहां अंतर है: "android.mk में LOCAL_STATIC_LIBRARIES के बजाय LOCAL_WHOLE_STATIC_LIBRARIES का उपयोग करें"
जोश

4

Ndk में ऐप्स के तहत एक उदाहरण है: https://github.com/android/ndk-samples/blob/master/hello-gl2/app/src/main/cpp/gl_code.cpp


2
आप एंड्रॉइड-एनडीके / नमूने / हैलो-
ग्ल 2


1
@ सात्विक यह फिर से मर चुका है।
माईगॉड


लिंक फिर से मर चुका है
user13107

2

जावा (जावा एसडीके का हिस्सा) का उपयोग करें। इसके लिए इसके उपकरण बिल्कुल। (.cl हैडर को .class फ़ाइल से उत्पन्न करता है)।


2

यदि आपके पैकेज के नाम में _ वर्ण शामिल है, तो आपको नीचे दिखाए गए अनुसार _ चरित्र के बाद 1 (एक) लिखना चाहिए:

MainActivity.java

package com.example.testcpp_2;

देशी-lib.cpp

JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(

0

मैं उपरोक्त सभी समाधानों की कोशिश करता हूं, लेकिन कोई भी मेरी बिल्ड त्रुटि (jni java.lang.UnsatisfiedLinkError: कोई कार्यान्वयन नहीं मिला ...) को हल कर सकता है, अंत में मैंने पाया कि मैं CMakeList.txt में अपनी verify.cpp स्रोत फ़ाइल जोड़ना भूल गया हूं add_library segement (सत्यापित करें। Ctrl + Ctrl + Enter छोटी कुंजी, शायद अन्य फ़ाइल नाम से ऑटो जेनरेट होता है), उम्मीद है कि मेरी प्रतिक्रिया कुछ मदद कर सकती है।

मेरा बिल्ड माहौल: ग्रेडले + सीएमके


0

मैंने उसी समस्या का सामना किया, और मेरे मामले में कारण यह था कि मेरे पास "RFID_Test" पैकेज नाम में अंडरस्कोर था, मैंने पैकेज का नाम बदला और यह काम किया। धन्यवाद user1222021


-3

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

  1. एंड्रॉइड स्टूडियो को नवीनतम संस्करण में अपग्रेड करें
  2. एंड्रॉइड स्टूडियो के भीतर से आवश्यक एपीआई डाउनलोड करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.