java - ndk中的原生调用错误

标签 java android c++ android-ndk

主 Activity .java

package com.example.android.testjni;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    final String TAG = "TestJni";
    static {
        System.loadLibrary("addjni");
        native_init();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        native_setup();
        Log.i(TAG, "after setup mNativeMainA=0x"+Long.toHexString(mNativeMainA));
        Button btn = (Button)findViewById(R.id.btn_id);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "add from jni:"+native_add(3,21));
            }
        });
    }

    private long mNativeMainA;
    private static native final void native_init();
    private native final int native_add(int a, int b);
    private native final void native_setup();
}

MainActivity_jni.cpp

#include <jni.h>
#include <stdint.h>I
#include <sys/types.h>

#include "MainActivity.h"

struct fields_t {
    // these fields provide access from C++ to the...
    jclass    clazzMainA; // MainActivity class
    jfieldID  fidMainA; //
};
static fields_t fields;
static const char* const kClassPathName = "com/example/android/testjni/MainActivity";

static void com_example_native_init(JNIEnv *env)
{
    // Get the AudioEffect class
    jclass clazz = env->FindClass(kClassPathName);
    if (clazz == NULL) {
        LOGV("Can't find %s", kClassPathName);
        return;
    }

    fields.clazzMainA = (jclass)env->NewGlobalRef(clazz);

    fields.fidMainA = env->GetFieldID(
            fields.clazzMainA,
            "mNativeMainA", "J");
    if (fields.fidMainA == NULL) {
        LOGV("Can't find fidMainA.%s", "mNativeMainA");
        return;
    }
    LOGV("native init over!");
}

static void com_example_native_setup(JNIEnv *env, jobject thiz)
{
    MainActivity *lpMainA = new MainActivity();
    LOGV("native setup!thiz=%p,lpMainA=0x%lx", thiz,(jlong)(lpMainA));
    env->SetLongField(thiz, fields.fidMainA, (jlong)(lpMainA));
}

static long getlpMainA(JNIEnv *env, jobject thiz)
{
    jlong lpmaina = env->GetLongField(thiz, fields.fidMainA);
    return lpmaina;
}

static int com_example_native_add(JNIEnv *env, jobject thiz,jint a, jint b)
{
    MainActivity *lpMainA = (MainActivity *)getlpMainA(env, thiz);
    LOGV("native add!a=%d,b=%d,lpMainA=0x%lx",a,b,(jlong)lpMainA);
    typedef int (*func_realadd_t)(void *thiz,int,int);
    func_realadd_t func_realadd = (func_realadd_t)(*(unsigned long *)(*(unsigned long *)lpMainA));
    LOGV("func_realadd=0x%lx", (jlong)func_realadd);
    int ret = func_realadd(thiz,a,b); //invoke method error
    //ret = lpMainA->real_add(a,b);
    LOGV("ret=%d", ret);

    return ret;
}

// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
    {"native_init",          "()V",      (void *)com_example_native_init},
    {"native_add",           "(II)I",    (void *)com_example_native_add},
    {"native_setup",         "()V",      (void *)com_example_native_setup}
};

jint JNI_OnLoad(JavaVM* vm, void* reserved __unused)
{
    JNIEnv* env = NULL;
    jint result = -1;
    jclass clazz;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGV("ERROR: GetEnv failed\n");
        goto bail;
    }
    clazz = env->FindClass(kClassPathName);
    if(clazz == NULL) {
        LOGV("find class error!");
        goto bail;
    }
    env->RegisterNatives(clazz, gMethods,  stores in Java the native MainActivity objectIsizeof(gMethods)/sizeof(gMethods[0]));

    result = JNI_VERSION_1_4;
bail:
    return result;
}

MainActivity.cpp://这是真正的函数代码

//
// Created by android on 17-4-19.
//
#include "MainActivity.h"
MainActivity::MainActivity()
{
LOGV("in MainActivity::MainActivity");
mStatus = 100;
}

int MainActivity::real_add(int a, int b)
{
    LOGV("in MainActivity virtual real_add,mStatus=%d", mStatus);
    if (mStatus == 100)
        return a+b;
    else
        return -22;
}

运行结果:

04-20 08:40:10.704 25953 25953 I TestJni+++++++: native init over!
04-20 08:40:10.756 25953 25953 I TestJni+++++++: in MainActivity::MainActivity
04-20 08:40:10.756 25953 25953 I TestJni+++++++: native setup!thiz=0x7ffc85cc04,lpMainA=0x790e6f2a30
04-20 08:40:10.756 25953 25953 I TestJni : after setup mNativeMainA=0x790e6f2a30
04-20 08:40:10.834   904   940 I ActivityManager: Displayed com.example.android.testjni/.MainActivity: +202ms
04-20 08:40:13.095 25953 25953 I TestJni+++++++: native add!a=3,b=21,lpMainA=0x790e6f2a30
04-20 08:40:13.095 25953 25953 I TestJni+++++++: func_realadd=0x7917264698
04-20 08:40:13.095 25953 25953 I TestJni+++++++: in MainActivity virtual real_add,mStatus=121
04-20 08:40:13.095 25953 25953 I TestJni+++++++: ret=-22
04-20 08:40:13.095 25953 25953 I TestJni : add from jni:-22

我的问题是为什么mStatus121,它应该被初始化为100。我对此很困惑。 我用谷歌搜索,但没有得到任何帮助。

谢谢

最佳答案

解决了

int ret = func_realadd(thiz,a,b); //invoke method error

改为

int ret = func_realadd(lpMainA,a,b); //it's okey!

关于java - ndk中的原生调用错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43514862/

相关文章:

java - 服务器和 iPhone/Android 客户端上的号码生成验证

java - 双击jar并在Mac上的命令提示符下运行同一jar时的不同行为

java - a4j :commandbutton not allowing "<" in rendered

java - 使用多个线程是不好的做法吗? (通过 SwingWorkers)

android - 没有 onStart 和 onStop + Google Analytics 的 Activity

android - 在 SSLContext 中使用硬件支持的 key

android - onChildClick 不适用于我的 ExpandableListView

c++ - 派生类对象的地址超过 1 个?

c++ - 为 Windows 7 编译 Windows 8 微过滤器驱动程序

c++ - 用于匹配以空格分隔的多个坐标的正则表达式