C++ C+的JNI+;类不满足FieldLinker错误

C++ C+的JNI+;类不满足FieldLinker错误,c++,c++11,java-native-interface,C++,C++11,Java Native Interface,嗨,伙计们 我知道这里有太多关于JNI的话题,但是,我是JNI的新手,所以我决定写一个新的 我试图编写一个JNI来访问Java层中的一些C++类,但我得到了错误: Exception in thread "main" java.lang.UnsatisfiedLinkError: arm.test.lib.FooClass.init(I)V at arm.test.lib.FooClass.init(Native Method) at arm.test.lib.FooClass.

嗨,伙计们

我知道这里有太多关于JNI的话题,但是,我是JNI的新手,所以我决定写一个新的

我试图编写一个JNI来访问Java层中的一些C++类,但我得到了错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: arm.test.lib.FooClass.init(I)V
    at arm.test.lib.FooClass.init(Native Method)
    at arm.test.lib.FooClass.<init>(FooClass.java:13)
    at arm.test.app.Main.main(Main.java:9)
<end of output>
foo文件夹中的CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
project(foo)

add_compile_options(-std=c++11)

set(PROJECT_PATH    ${CMAKE_CURRENT_SOURCE_DIR})
set(SRCS_PATH       "${PROJECT_PATH}/src")
set(CPPLIB_INCLUDE_DIR  "${PROJECT_PATH}/include" CACHE INTERNAL "foo include directories") 

include_directories(${CPPLIB_INCLUDE_DIR})

file(GLOB SRCS "${SRCS_PATH}/*.cpp" "${SRCS_PATH}/*.h")

add_library(${PROJECT_NAME} SHARED ${SRCS})
Foo是一个简单的类、构造函数和一些函数

福安 foo.cpp C路径中是C到java的包装器

#include  "foo.h"

#include "FooClass_jni.h"

static jfieldID _get_self_id(JNIEnv *env, jobject thisObj)
{
    static int init = 0;
    static jfieldID fidSelfPtr;
    if(!init)
    {
        jclass thisClass = env->GetObjectClass(thisObj);
        fidSelfPtr = env->GetFieldID(thisClass, "self_ptr", "J");
    }
    return fidSelfPtr;
}
static Foo *_get_self(JNIEnv *env, jobject thisObj)
{
    jlong selfPtr = env->GetLongField(thisObj, _get_self_id(env, thisObj));
    return *(Foo**)&selfPtr;
}

static void _set_self(JNIEnv *env, jobject thisObj, Foo *self)
{
    jlong selfPtr = *(jlong*)&self;
    env->SetLongField(thisObj, _get_self_id(env, thisObj), selfPtr);
}


extern "C" JNIEXPORT void JNICALL Java_arm_test_lib_Foo_init(JNIEnv *env, jobject thisObj, jint nb)
{
    Foo *self = new Foo(nb);
    _set_self(env, thisObj, self);
}

extern "C" JNIEXPORT jint JNICALL Java_arm_test_lib_Foo_getValue(JNIEnv *env, jobject thisObj)
{
    Foo *self = _get_self(env, thisObj);
    return self->getValue();
}

extern "C" JNIEXPORT void JNICALL Java_arm_test_lib_Foo_increment(JNIEnv *env, jobject thisObj)
{
    Foo *self = _get_self(env, thisObj);
    self->increment();
}

extern "C" JNIEXPORT void JNICALL Java_arm_test_lib_Foo_finalize(JNIEnv *env, jobject thisObj)
{
    Foo *self = _get_self(env, thisObj);
    if(self != NULL)
    {
        delete self;
        _set_self(env, thisObj, NULL);
    }
}
当我在javajni中运行cmake文件时,javah将生成这个文件

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

#ifndef _Included_arm_test_lib_FooClass
#define _Included_arm_test_lib_FooClass
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     arm_test_lib_FooClass
 * Method:    init
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_arm_test_lib_FooClass_init
  (JNIEnv *, jobject, jint);

/*
 * Class:     arm_test_lib_FooClass
 * Method:    getValue
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_arm_test_lib_FooClass_getValue
  (JNIEnv *, jobject);

/*
 * Class:     arm_test_lib_FooClass
 * Method:    increment
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_arm_test_lib_FooClass_increment
  (JNIEnv *, jobject);

/*
 * Class:     arm_test_lib_FooClass
 * Method:    finalize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_arm_test_lib_FooClass_finalize
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
该代码可在以下位置获得:


致以最诚挚的问候。

您的jni\U包装器.cpp是为Java类Foo编写的,但是您尝试从类FooClass

使用它。代码必须在这里可用。是的!你说得对,谢谢!我将函数
Java\u arm\u test\u lib\u Foo
重新命名为
Java\u arm\u test\u lib\u Foo class
,并成功运行。如果您接受答案,JNI将运行得更好;)
#include <iostream>

#include "foo.h"


    Foo::Foo(int &n_nb) :m_nb(n_nb)
    {
        std::cout << n_nb << std::endl;
    }

    int Foo::getValue() const 
    {
        return this->m_nb;
    }

    void Foo::increment()
    {
        this->m_nb++;
    }
cmake_minimum_required(VERSION 2.8)

# REQUIRED JAVA
FIND_PACKAGE(Java COMPONENTS Development)
INCLUDE(UseJava)
SET(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.8" "-target" "1.8")

SET(JAVA_SOURCE_FILES 
arm/test/app/Main.java 
arm/test/lib/FooClass.java)


# Build Java classes
FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/java/bin")
SET(class_files)
FOREACH(_java_file ${JAVA_SOURCE_FILES})
    # _java_file: relative file name
    # _class_file: relative class name
    STRING(REGEX REPLACE "\\.java$"
       ".class" _class_file
           "${_java_file}")
    ADD_CUSTOM_COMMAND(
        OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/java/bin/${_class_file}"
        COMMAND
            ${Java_JAVAC_EXECUTABLE}
            ${CMAKE_JAVA_COMPILE_FLAGS}
            -sourcepath "${CMAKE_CURRENT_SOURCE_DIR}/java/src"
            -d "${CMAKE_CURRENT_BINARY_DIR}/java/bin"
            "${CMAKE_CURRENT_SOURCE_DIR}/java/src/${_java_file}"
        DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/java/src/${_java_file}")
    LIST(APPEND class_files "java/bin/${_class_file}")
ENDFOREACH()

ADD_CUSTOM_TARGET(JavaJNIClasses ALL DEPENDS ${class_files})

# Make the JNI header file
ADD_CUSTOM_COMMAND(
    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/FooClass_jni.h"
    COMMAND
        ${Java_JAVAH_EXECUTABLE}
        -o "${CMAKE_CURRENT_BINARY_DIR}/include/FooClass_jni.h"
        -classpath "${CMAKE_CURRENT_BINARY_DIR}/java/bin"
        arm.test.lib.FooClass
    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/java/bin/arm/test/lib/FooClass.class")
ADD_CUSTOM_TARGET(JavaJNIHeaders ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/FooClass_jni.h")

# Require JNI
FIND_PACKAGE(JNI REQUIRED)

# Builds the JNI wrapper
INCLUDE_DIRECTORIES("${CPPLIB_INCLUDE_DIR}"
                   "${CMAKE_CURRENT_BINARY_DIR}/include"
                    ${JNI_INCLUDE_DIRS}
)

ADD_LIBRARY(foo_jni SHARED c/jni_wrapper.cpp)

link_directories("${CMAKE_BINARY_DIR}/foo")

SET_TARGET_PROPERTIES(
    foo_jni PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_BINARY_DIR}"
    LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_BINARY_DIR}"
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_BINARY_DIR}"
    RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_BINARY_DIR}")

TARGET_LINK_LIBRARIES(foo_jni foo)

ADD_DEPENDENCIES(foo_jni JavaJNIHeaders)

# Testing
IF(BUILD_TESTS)
    FIND_PACKAGE(Java COMPONENTS Runtime)
    ADD_TEST(
        NAME run-jni
        COMMAND
            "${Java_JAVA_EXECUTABLE}"
            -cp java-jni/java/bin
            -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}
            arm.test.app.Main
        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
ENDIF()
#include  "foo.h"

#include "FooClass_jni.h"

static jfieldID _get_self_id(JNIEnv *env, jobject thisObj)
{
    static int init = 0;
    static jfieldID fidSelfPtr;
    if(!init)
    {
        jclass thisClass = env->GetObjectClass(thisObj);
        fidSelfPtr = env->GetFieldID(thisClass, "self_ptr", "J");
    }
    return fidSelfPtr;
}
static Foo *_get_self(JNIEnv *env, jobject thisObj)
{
    jlong selfPtr = env->GetLongField(thisObj, _get_self_id(env, thisObj));
    return *(Foo**)&selfPtr;
}

static void _set_self(JNIEnv *env, jobject thisObj, Foo *self)
{
    jlong selfPtr = *(jlong*)&self;
    env->SetLongField(thisObj, _get_self_id(env, thisObj), selfPtr);
}


extern "C" JNIEXPORT void JNICALL Java_arm_test_lib_Foo_init(JNIEnv *env, jobject thisObj, jint nb)
{
    Foo *self = new Foo(nb);
    _set_self(env, thisObj, self);
}

extern "C" JNIEXPORT jint JNICALL Java_arm_test_lib_Foo_getValue(JNIEnv *env, jobject thisObj)
{
    Foo *self = _get_self(env, thisObj);
    return self->getValue();
}

extern "C" JNIEXPORT void JNICALL Java_arm_test_lib_Foo_increment(JNIEnv *env, jobject thisObj)
{
    Foo *self = _get_self(env, thisObj);
    self->increment();
}

extern "C" JNIEXPORT void JNICALL Java_arm_test_lib_Foo_finalize(JNIEnv *env, jobject thisObj)
{
    Foo *self = _get_self(env, thisObj);
    if(self != NULL)
    {
        delete self;
        _set_self(env, thisObj, NULL);
    }
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class arm_test_lib_FooClass */

#ifndef _Included_arm_test_lib_FooClass
#define _Included_arm_test_lib_FooClass
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     arm_test_lib_FooClass
 * Method:    init
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_arm_test_lib_FooClass_init
  (JNIEnv *, jobject, jint);

/*
 * Class:     arm_test_lib_FooClass
 * Method:    getValue
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_arm_test_lib_FooClass_getValue
  (JNIEnv *, jobject);

/*
 * Class:     arm_test_lib_FooClass
 * Method:    increment
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_arm_test_lib_FooClass_increment
  (JNIEnv *, jobject);

/*
 * Class:     arm_test_lib_FooClass
 * Method:    finalize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_arm_test_lib_FooClass_finalize
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
package arm.test.lib;

public class FooClass{

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

    private long self_ptr;

    public FooClass(int nb)
    {
        init(nb);
    }

    private native void init(int nb);

    public native int getValue();

    public native void increment();

    protected native void finalize();

}