简体   繁体   English

Android NDK / JNI - 自定义 header 文件中定义的对 function 的未定义引用

[英]Android NDK / JNI - undefined reference to function defined in custom header file

Using JNI, I am trying to write a native C++ method for the Android NDK that makes a call to a C function defined in a custom header file.使用 JNI,我正在尝试为 Android NDK 编写本机 C++ 方法,该方法调用自定义 header 文件中定义的 C function。 However, I am getting an undefined reference error for my C function call.但是,我的 C function 调用出现未定义的引用错误。

Here is my C++ code that makes a call to the C function and returns its result to Java as a jstring:这是我的 C++ 代码,它调用 C function 并将其结果作为 jstring 返回给 Java:

#include <jni.h>

#include "gesture_detector.h"

JNIEXPORT jstring JNICALL Java_com_example_bmtitest_JavaAbstractionLayer_callGestureAnalysis(JNIEnv *env, jobject obj, jfloat previousX, jfloat previousY, jfloat currentX, jfloat currentY) {
    return env->NewStringUTF(gestureAnalysis(previousX, previousY, currentX, currentY));
}

Here is my C function:这是我的 C function:

#include <stdio.h>

#include "gesture_detector.h"

//implemented from gesture_detector.h
const char* gestureAnalysis(float previousX, float previousY, float currentX, float currentY)
{
    float xOffset = currentX - previousX;
    float yOffset = currentY - previousY;

    if(xOffset == 0 && yOffset == 0)
    {
        return "TAP";
    }
    return "0";
}

Here is my Android.mk code:这是我的 Android.mk 代码:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := gestureDetector
LOCAL_SRC_FILES := gestureDetector.c NativeAbstractionLayer.cpp
LOCAL_LDLIBS    := -landroid

include $(BUILD_SHARED_LIBRARY)

Apparently, it seems the function definition defined in the custom header file ( gesture_detector.h ) isn't being found.显然,似乎找不到自定义 header 文件 ( gesture_detector.h ) 中定义的 function 定义。 I think it may be a problem in my Android.mk file.我认为这可能是我的 Android.mk 文件中的问题。

Could anyone tell me what am I doing wrong here?谁能告诉我我在这里做错了什么?

An "undefined reference" error comes from the linker . 链接器出现“未定义引用”错误。 Your header file only satisfied the compiler. 您的头文件仅满足编译器的要求。

However, since you are mixing C and C++ your problem is likely name mangling . 但是,由于您混合使用C和C ++,因此您的问题很可能是名称修改 Basically, you need to tell the C++ compiler that the function you are trying to call was created by a C compiler rather than a C++ one, and so does not have argument type codes grafted onto its name. 基本上,您需要告诉C ++编译器您要调用的函数是由C编译器而非C ++编译器创建的,因此其名称上没有嫁接参数类型代码。 Right now it doesn't know that, so is trying to call the function by a C++ style decorated name which differs from the plain C name of the function the linker actually has available. 现在,它尚不知道,因此正在尝试使用C ++样式修饰的名称来调用该函数,该名称不同于链接器实际可用的普通C名称。

Add this at the beginning of your gesture_detector.h file: 将此添加到您的gesture_detector.h文件的开头:

#ifdef __cplusplus
extern "C" {
#endif

And this at the end 最后这个

#ifdef __cplusplus
}
#endif

And do a clean rebuild. 并进行干净的重建。

If your real jni glue logic is as trivial as the version presented here, switching to a C version of that could also be an option - but beware that jni syntax is different in C and C++, so you can't just change the file extension. 如果您真正的jni胶合逻辑与此处介绍的版本一样琐碎,则也可以选择将其切换为C版本-但请注意,jni语法在C和C ++中是不同的,因此您不能只更改文件扩展名。

Simply doing your native C++- code between 只需在之间执行本机C ++代码

extern "C" {
    your code
}

Is something that not always will necessarily work - as you can check here . 并非总是能奏效的事情-您可以在这里查看

Try adding to the Android.mk file: 尝试添加到Android.mk文件中:

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

Here you find further info about it. 在这里,您可以找到有关它的更多信息

In my case, my project was building properly but it started giving the 'undefined reference' error after I added two new files somefile.h and somefile.c.就我而言,我的项目构建正常,但在我添加两个新文件 somefile.h 和 somefile.c 后它开始出现“未定义引用”错误。 I added these files to the source directory of a existing library I built so no changes in cmake were required for referring to the new files.我将这些文件添加到我构建的现有库的源目录中,因此不需要更改 cmake 来引用新文件。 Cleaning and rebuilding project didn't work.清洁和重建项目没有奏效。 However, I made some redundant changes in my CMakeLists.txt file and then did a clean rebuild.但是,我在我的 CMakeLists.txt 文件中做了一些多余的更改,然后进行了干净的重建。 The build was successful.构建成功。 After that I removed this change (since it is redundant) and tried doing a clean rebuild again and the code was working.之后我删除了这个更改(因为它是多余的)并尝试再次进行干净的重建并且代码正在运行。 Maybe the build system was fetching some objects from cache, and changing CMakeLists.txt forced it to build the objects again from scratch.也许构建系统正在从缓存中获取一些对象,并且更改 CMakeLists.txt 迫使它从头开始构建对象。 If anyone knows why such behaviour is observed please let me know.如果有人知道为什么会观察到这种行为,请告诉我。 Thanks!谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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