在 android 中使用 JNI 对 'multiply' 的未定义引用
undefined reference to 'multiply' using JNI in android
我是 android JNI
的新手,正在尝试以下代码:
包名称: 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 文件
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)
我有预构建 com_example_pdemo_MainActivity.so lib 放在 JNI-> armeabi(写入多个函数)文件夹中包含在 Android.mk 文件
JNI 内部:
使用以下命令创建头文件: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
本机函数的定义: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);
}
当我编译它时,我得到了对'multiply'的未定义引用。请告诉我我犯了什么错误。
提前致谢..
multiply 也是本地方法。它的定义应与 sumOfTwovariable:
相同
JNIEXPORT jlong JNICALL Java_com_example_jnitest_MainActivity_multiply(JNIEnv *, jobject, jint, jint);
在 com_example_pdemo_MainActivity.so 的本机代码中,像这样定义乘法:
// 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);
}
这将允许您从本机代码或通过 JNI 调用它。
将您的 Android.mk 文件更改为此,将预构建的 .so 文件放在第一位:
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)
最后,在您的 Java 代码中,将两个库加载到一个静态块中,顺序如下:
static{
System.loadLibrary("com_example_pdemo_MainActivity");
System.loadLibrary("JNITest");
}
JNITest 需要 com_example_pdemo_MainActivity,因此它需要先进行,否则您将遇到运行时 link 错误。
此外,在 JNITest.cpp 中,删除围绕 multiply() 声明的 extern "C"
。如果您使用 C++ linkage 编译了 com_example_pdemo_MainActivity.so 文件,那么在尝试使用 JNITest link 时使用 C extern 将导致 link 错误:
// extern "C"{ <-- remove
long multiply(int v1,int v2);
//} <-- remove
如何在字节缓冲区中将数据传入和传出 JNI:
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;
}
我是 android JNI
的新手,正在尝试以下代码:
包名称: 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 文件
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)
我有预构建 com_example_pdemo_MainActivity.so lib 放在 JNI-> armeabi(写入多个函数)文件夹中包含在 Android.mk 文件
JNI 内部:
使用以下命令创建头文件: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
本机函数的定义: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);
}
当我编译它时,我得到了对'multiply'的未定义引用。请告诉我我犯了什么错误。
提前致谢..
multiply 也是本地方法。它的定义应与 sumOfTwovariable:
相同JNIEXPORT jlong JNICALL Java_com_example_jnitest_MainActivity_multiply(JNIEnv *, jobject, jint, jint);
在 com_example_pdemo_MainActivity.so 的本机代码中,像这样定义乘法:
// 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);
}
这将允许您从本机代码或通过 JNI 调用它。
将您的 Android.mk 文件更改为此,将预构建的 .so 文件放在第一位:
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)
最后,在您的 Java 代码中,将两个库加载到一个静态块中,顺序如下:
static{
System.loadLibrary("com_example_pdemo_MainActivity");
System.loadLibrary("JNITest");
}
JNITest 需要 com_example_pdemo_MainActivity,因此它需要先进行,否则您将遇到运行时 link 错误。
此外,在 JNITest.cpp 中,删除围绕 multiply() 声明的 extern "C"
。如果您使用 C++ linkage 编译了 com_example_pdemo_MainActivity.so 文件,那么在尝试使用 JNITest link 时使用 C extern 将导致 link 错误:
// extern "C"{ <-- remove
long multiply(int v1,int v2);
//} <-- remove
如何在字节缓冲区中将数据传入和传出 JNI:
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;
}