【问题标题】:call java function from c++ (jni) isn't working at all从c ++(jni)调用java函数根本不起作用
【发布时间】:2013-03-25 18:58:26
【问题描述】:

我在网上找到了很多帖子,但似乎没有一个可以帮助我做对..

我的问题是我想从 ndk c++ 部分调用一个 android java 函数..

当我上课时:

jclass icls = jenv->GetObjectClass(obj);

我收到此错误: E/AndroidRuntime(27397): java.lang.NoSuchMethodError: 在类 Ljava/lang/Class 中没有 name='setValues' signature='()V' 的方法; => jmid == 0

当我用 "FindClass" 像下面这样调用它时,我收到此错误:A/libc(26692): Fatal signal 11 (SIGSEGV) at 0x00000004 (code=1), thread 26743(线程 8302)

findclass 和方法似乎可以工作 (!= 0) 那么 obj 会不会有问题?

有人吗?提前谢谢..

JAVA - 主类:

package com.new.test;
class Test{
   public Test(Context context, AttributeSet attrs) {
        super(context, attrs);
        run();
   }

   run(){
         int x = 10;
         new DoStuff(x);
   }
   public void setValues(){     
       Log.e("","SET VALUES");
   }
}

JAVA 2 JNI:

public class DoStuff{   
    public DoStuff(int x){
        nativeDoStuff(x);
    }

    private static native long nativeDoStuff(int x);

    static{
        System.loadLibrary("do_stuff");
    }
}

C++:cpp

JNIEXPORT void JNICALL Java_com_new_test_DoStuff_nativeDoStuff (JNIEnv * jenv, jobject obj, jint x){

    jclass icls = jenv->FindClass("com/new/test/Test");
    //jclass icls = jenv->GetObjectClass(obj);
    jmethodID jmid = jenv->GetMethodID(icls, "setValues","()V");
    jenv->CallVoidMethod(obj,jmid);

}

C++:h

JNIEXPORT void JNICALL Java_com_new_test_DoStuff_nativeDoStuff (JNIEnv *, jobject, jint);

【问题讨论】:

    标签: java android c++ android-ndk java-native-interface


    【解决方案1】:

    方法Test.setValues() 是一个实例方法——它需要一个有效的Test 对象才能执行。同时,方法nativeDoStuff 没有。它是一个静态方法,它所拥有的(作为第二个参数)是 DoStuff 类的一个类对象。您错误地将该类指针作为this 指针传递给CallVoidMethod() - 这是致命的错误。

    将所有内容移到一个类中(TestDoStuff,没关系)并在 Java 端将 nativeDoStuff() 声明为非静态的。或者将doStuff() 本身设为静态并使用jenv->CallStaticVoidMethod() 作为最后一行。

    【讨论】:

    • 哦,非常感谢!从来没有想过,因为它以前工作过(当然因为我没有使用obj)..我把所有东西都移到了Test并从nativeDoStuff()中删除了静态..这有什么缺点吗?我用使它成为静态的,因为它在 opencv 中是这样的。
    • 静态方法的调用开销略少(没有this 可以传递)。但在某些时候,您可能需要this 来回调Java。您的来电。
    【解决方案2】:

    如果我没看错的话,在这种情况下,“obj”将指向 DoStuff 对象,而不是 Test 对象。因此,您尝试在不包含此方法的对象上调用 setValues 方法。您应该使您的本机方法成为 Test 的成员,或者将 Test 的实例传递给函数。

    【讨论】:

    • ok ic.. 但我也尝试将“setValues”函数放在“DoStuff”类中,但没有成功。那不应该吗?或者你能给我一个如何传递实例的例子吗?
    • 我已将 setValues 再次放入 DoStuff 并收到此错误:"E/dalvikvm(31575): JNI 错误(应用程序错误):访问过时的全局引用 0x341c3722(索引 3528 在大小 139) E/dalvikvm(31575):VM 在 0xdeadd00d (code=1) 处中止致命信号 11 (SIGSEGV),线程 31636 (Thread-8398)"
    • 我添加(并将所有 obj 更改为 javaObj):jobject javaObj = jenv->NewGlobalRef(obj);但我似乎没有在 0xdeadd00d (code=1), thread 31636 (Thread-8398)"* 处使用致命信号 11 (SIGSEGV)
    • ok sry for spaming :) 但我也尝试将 DoStuff 包含在测试类中,它似乎更进一步......现在我收到了这个错误 03-25 20: 54:43.280: E/AndroidRuntime(2682): FATAL EXCEPTION: Thread-8470 03-25 20:54:43.280: E/AndroidRuntime(2682): java.lang.AbstractMethodError 但似乎没有进入 setValues 类(它不记录任何东西)
    • 感谢您的帮助.. Seva 和您是对的,这是静态问题或您提到的 obj 错误。我将一个 Test 实例传递给 DoStuff 并从那里传递给 nativeDoStuff 并将其用于调用。工作​​就像一个魅力,我昨天没做对:)
    【解决方案3】:

    尝试更改以下内容中的空白:

    JNIEXPORT void JNICALL Java_com ...
    

    jlong​​

    【讨论】:

    • thx,但我没有返回任何东西(我想说).. Seva 的答案现在似乎有效。
    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 2019-04-09
    相关资源
    最近更新 更多