অ্যান্ড্রয়েডে সি ++ থেকে জাভা পদ্ধতি কল করা


91

আমি জাভা দেশীয় পদ্ধতিতে কল করার সময় সি ++ থেকে একটি সাধারণ জাভা পদ্ধতি কল পাওয়ার চেষ্টা করছি। জাভা কোডটি এখানে:

public class MainActivity extends Activity {
    private static String LIB_NAME = "name";

    static {
        System.loadLibrary(LIB_NAME);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = (TextView) findViewById(R.id.textview);
        tv.setText(this.getJniString());
    }

    public void messageMe(String text) {
        System.out.println(text);
    }

    public native String getJniString();
}

আমি জাভা থেকে নেটিভ পদ্ধতিতে পদ্ধতি কল messageMeপ্রক্রিয়াতে নেটিভ কোড থেকে পদ্ধতি কল করার চেষ্টা করছি getJniString*

নেটি.সিপি:

#include <string.h>
#include <stdio.h>
#include <jni.h>

jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj, jint depth ){

//    JavaVM *vm;
//    JNIEnv *env;
//    JavaVMInitArgs vm_args;
//    vm_args.version = JNI_VERSION_1_2;
//    vm_args.nOptions = 0;
//    vm_args.ignoreUnrecognized = 1;
//
//    // Construct a VM
//    jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);

    // Construct a String
    jstring jstr = env->NewStringUTF("This string comes from JNI");
    // First get the class that contains the method you need to call
    jclass clazz = env->FindClass("the/package/MainActivity");
    // Get the method that you want to call
    jmethodID messageMe = env->GetMethodID(clazz, "messageMe", "(Ljava/lang/String;)V");
    // Call the method on the object
    jobject result = env->CallObjectMethod(jstr, messageMe);
    // Get a C-style string
    const char* str = env->GetStringUTFChars((jstring) result, NULL);
    printf("%s\n", str);
        // Clean up
    env->ReleaseStringUTFChars(jstr, str);

//    // Shutdown the VM.
//    vm->DestroyJavaVM();

    return env->NewStringUTF("Hello from JNI!");
}

পরিষ্কার সংকলন অ্যাপ্লিকেশন পরবর্তী বার্তা সহ বন্ধ হয়ে যায়:

ERROR/AndroidRuntime(742): FATAL EXCEPTION: main
        java.lang.NoSuchMethodError: messageMe
        at *.android.t3d.MainActivity.getJniString(Native Method)
        at *.android.t3d.MainActivity.onCreate(MainActivity.java:22)

স্পষ্টতই এর অর্থ হ'ল পদ্ধতির নামটি ভুল, তবে এটি আমার কাছে ঠিক আছে।


21
আপনার প্রশ্ন এবং সমাধান উভয়ই পড়া সহজ করে এবং এইভাবে সম্প্রদায়ের জন্য আরও দরকারী করার জন্য দয়া করে আপনার সমাধানটি একটি সাধারণ উত্তর হিসাবে পোস্ট করুন। ইতিমধ্যে তাদের উত্তরগুলি সম্পূর্ণরূপে জবাব দেওয়া অন্য ব্যক্তির সাথেও আপনি সহযোগিতা করতে পারেন।
Misiu_mp

@ ডেনিস: আমি আপনার কোডিং অনুসরণ করেছি, তবে আমি এই ত্রুটিটি পেয়েছি: java.lang.UnsatisectedLinkError: getJniString। আপনি কি আমাকে এই ত্রুটিটি ঠিক করতে সহায়তা করতে পারেন?
হুই টাওয়ার

@ অ্যালেক্সট্রান, এটি অনেক দিন আগে কিন্তু ত্রুটিটি থেকে বিচার করে আপনি সম্ভবত ভুল বানানটি ব্যবহার করেছেন বা getJniStringপদ্ধতিটি জাভা বা সি তে লিঙ্ক করেননি । সিস্টেম কোড আমদানি করে সম্ভবত সি কোডটি জাভাতে লিঙ্ক করার বিষয়টি নিশ্চিত করুন (এখনই এই সমস্ত জিনিস মনে রাখবেন না: পি)
ডেনিস এস

4
এটি সি থেকে জাভা পদ্ধতিটি কল করছে কীভাবে? এটি স্পষ্টতই জাভা এর onCreateপদ্ধতিটি আপনার নেটিভ সিটিকে কল করছে
জন

আমি পরিবেশের (এনভি) ভেরিয়েবলের সাথে এক্সিকিউট করার সময় '->' এর বেস -অপারেণ্ড পাচ্ছি 'জেএনআইইএনভ' নন-পয়েন্টার টাইপ রয়েছে । এছাড়াও এনভি * পরিবর্তনশীল যেমন জেএনআই থেকে জাভা স্তরে কলব্যাকের মতো করতে চাইলে কী হবে! যেকোনো পরামর্শ!
CoDe

উত্তর:


45

যদি এটি কোনও অবজেক্ট পদ্ধতি হয় তবে আপনাকে অবজেক্টটি এখানে পাঠাতে হবে CallObjectMethod:

jobject result = env->CallObjectMethod(obj, messageMe, jstr);

আপনি যা করছেন তার সমতুল্য ছিল jstr.messageMe()

যেহেতু আপনার একটি অকার্যকর পদ্ধতি, আপনার কল করা উচিত:

env->CallVoidMethod(obj, messageMe, jstr);

আপনি যদি কোনও ফলাফল ফিরে আসতে চান তবে আপনাকে আপনার জেএনআই স্বাক্ষর ( ()Vমানে voidরিটার্নের ধরণের একটি পদ্ধতি ) এবং আপনার জাভা কোডে রিটার্নের ধরণটি পরিবর্তন করতে হবে ।


দয়া করে, আমার PS এর কারণে, এটি কীভাবে করবেন তা সম্পর্কে আমাকে গাইড করুন :)
ডেনিস এস

আপনি যা পরামর্শ দিচ্ছেন তা দিয়ে আমি একই ফল পেয়েছি।
ডেনিস এস

4
প্রকৃতপক্ষে একটি কলভয়েডমেথড, কলবজেক্টমথোড ইত্যাদি রয়েছে each যেহেতু আপনার বার্তাটি আমার পদ্ধতিটি (লাজভা / ল্যাং / স্ট্রিং;) ভি, তাই আপনার কলভিডমেথোদ ব্যবহার করা দরকার।
ম্যাথু উইলিস

4
নোট করুন যে আপনি যে ত্রুটিটি পাচ্ছেন সম্ভবত তা ইঙ্গিত করে যে আপনার জাভা নেটিভ পদ্ধতিটি (আপনার জাভা কোডে) সম্ভবত শূন্য রিটার্ন টাইপের নয় এবং তাই গেটমেথোডিআইডি দ্বারা পাওয়া যায় নি
ম্যাথিউ উইলিস

10

প্রশ্ন পোস্টে ডেনিস এস পোস্ট করেছেন সমাধান :

আমি সি থেকে সি ++ রূপান্তর (মূলত envভেরিয়েবল স্টাফ) দিয়ে এটিকে বেশ বিভ্রান্ত করেছিলাম , তবে আমি সি ++ এর জন্য নিম্নলিখিত কোডের সাথে এটি কাজ করেছিলাম:

#include <string.h>
#include <stdio.h>
#include <jni.h>

jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){

    jstring jstr = (*env)->NewStringUTF(env, "This comes from jni.");
    jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity");
    jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
    jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr);

    const char* str = (*env)->GetStringUTFChars(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :)
    printf("%s\n", str);

    return (*env)->NewStringUTF(env, str);
}

এবং জাভা পদ্ধতিগুলির জন্য পরবর্তী কোড:

    public class MainActivity extends Activity {
    private static String LIB_NAME = "thelib";

    static {
        System.loadLibrary(LIB_NAME);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = (TextView) findViewById(R.id.textview);
        tv.setText(this.getJniString());
    }

    // please, let me live even though I used this dark programming technique
    public String messageMe(String text) {
        System.out.println(text);
        return text;
    }

    public native String getJniString();
}

না nativeপদ্ধতি স্ট্যাটিক হলে কি চলে?
ইগোরগানাপলস্কি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.