简体   繁体   中英

undefined reference to 'multiply' using JNI in android

I am new in android JNI and trying below code:

Package Name : com.example.jnitest

Java class:

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MainActivity mainActivity = new MainActivity();


    System.out.println("Sum of two variables : "+ sumOfTwovariable((int)mainActivity.multiply(10, 25), 10));
}

public native long sumOfTwovariable(int v1, int v2);

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

public native long multiply(int v1, int v2);
static{
    System.loadLibrary("com_example_pdemo_MainActivity");
}

}

Android.mk file

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := JNITest
LOCAL_SRC_FILES := JNITest.cpp
LOCAL_SHARED_LIBRARIES := Prebuild_com_example_pdemo_MainActivity
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includes
LOCAL_STATIC_LIBRARIES := Prebuild_com_example_pdemo_MainActivity
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_MODULE    := Prebuild_com_example_pdemo_MainActivity
LOCAL_SRC_FILES :=    $(TARGET_ARCH_ABI)/libcom_example_pdemo_MainActivity.so

include $(PREBUILT_SHARED_LIBRARY)

I have prebuild com_example_pdemo_MainActivity.so lib placed inside JNI-> armeabi(write multiple function) folder include in Android.mk file


Inside JNI :

Create the header file using : javah -jni -classpath....

Header file created using javah : com_example_jnitest_MainActivity.h

  /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_MainActivity */

#ifndef _Included_com_example_jnitest_MainActivity
#define _Included_com_example_jnitest_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_jnitest_MainActivity
  * Method:    sumOfTwovariable
  * Signature: (II)J
*/
JNIEXPORT jlong JNICALL    Java_com_example_jnitest_MainActivity_sumOfTwovariable(JNIEnv *, jobject, jint, jint);

 #ifdef __cplusplus
 }
#endif

#endif

Defination of the native function :JNITest.cpp

  #include "com_example_jnitest_MainActivity.h"

extern "C" {
long multiply(int val1,int val2);
}

   JNIEXPORT jlong JNICALL      Java_com_example_jnitest_MainActivity_sumOfTwovariable(
    JNIEnv *env, jobject obj, jint val1, jint val2) {
int val=multiply(val1,val2);
return (val+val1);

}

When i compile it, i got undefined reference to 'multiply'.Let me know what mistake i have done.

Thanks in Advance..

multiply is also native method. It should be defined as same as sumOfTwovariable:

JNIEXPORT jlong JNICALL    Java_com_example_jnitest_MainActivity_multiply(JNIEnv *, jobject, jint, jint);

Inside your native code for com_example_pdemo_MainActivity.so, define multiply like this:

// this can be called from native code, including in different .so files:
long multiply(int val1,int val2)
{
    long result;
    // ...compute result...
    return result;
}

// this can be called from Java via JNI:
JNIEXPORT jlong JNICALL Java_com_example_pdemo_MainActivity_multiply(JNIEnv *env, jobject obj, jint a, jint b)
{
     return multiply(a, b);
}

This will allow you to call it from native code or via JNI.

Change your Android.mk file to this, putting the prebuilt .so file first:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := Prebuild_com_example_pdemo_MainActivity
LOCAL_SRC_FILES :=    $(TARGET_ARCH_ABI)/libcom_example_pdemo_MainActivity.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := JNITest
LOCAL_SRC_FILES := JNITest.cpp
LOCAL_SHARED_LIBRARIES := Prebuild_com_example_pdemo_MainActivity
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includes
include $(BUILD_SHARED_LIBRARY)

Lastly, inside your Java code, load both libraries inside a single static block, in this order:

static{
    System.loadLibrary("com_example_pdemo_MainActivity");
    System.loadLibrary("JNITest");
}

JNITest needs com_example_pdemo_MainActivity so it needs to go first or you'll get a runtime link error.

Also, in JNITest.cpp, remove the extern "C" surrounding the declaration of multiply(). If you have compiled your com_example_pdemo_MainActivity.so file with C++ linkage then using a C extern will cause a link error when trying to link with JNITest:

// extern "C"{ <-- remove
    long multiply(int v1,int v2);
//} <-- remove

How to pass data to and from JNI in byte buffers:

JNIEXPORT int JNICALL Java_com_example_jnitest_MainActivity_compressImage(JNIEnv *pEnv, jobject this, jobject inputByteBuffer, jobject outputByteBuffer)
{
    jbyte* pInBuf = (jbyte*)(*pEnv)->GetDirectBufferAddress(pEnv, inputByteBuffer);
    jbyte* pOutBuf = (jbyte*)(*pEnv)->GetDirectBufferAddress(pEnv, outputByteBuffer);

    int lenOutImage = 0; char *pOutputImage;
    pOutputImage = CompressImage((char *)pInBuf,&lenOutImage);

    // copy to byte buffer
    memcpy((char)pOutBuf, pOutputImage, lenOutImage);        
    free(pOutputImage); // free pOutputImage?

    return lenOutImage;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM