编译一个大型 C++使用 JNI 将库导入 Android NDK - Makefile 问题

发布于 2024-09-24 09:26:11 字数 3006 浏览 2 评论 0原文

我正在尝试编译一个带有几个 Java 包装器的 C++ 库 (VRPN),以便在 Android 应用程序中使用。使用 ndk-build 命令,我的 C++ 接口文件的第一行出现“未定义的引用”错误,该文件引用库中对象的构造函数。我相当确定我的代码是正确的 - 调用与方法头匹配,并且我有头文件和源文件来验证它是否已实现。我认为问题出在我的 Android.mk 文件上,该文件当前仅引用我的单个类。因此,代码似乎可以编译,但一旦无法找到库其余部分的目标代码,就不会链接。我对 C++ 还很陌生,所以我对 makefile 不太了解,但我见过的“标准”makefile 都与 Android NDK 使用的 makefile 不匹配,这显然隐藏了很多细节。如果我理解正确的话,在“标准”makefile中,我只需命名输出文件及其需要的目标文件,然后是目标文件及其源文件和头文件等。我不知道如何强制 ndk-构建以创建目标代码并链接库的其余部分。

这是我当前的 Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jni_vrpn_button
LOCAL_SRC_FILES := jni_vrpn_button.cpp

include $(BUILD_SHARED_LIBRARY)

jni_vrpn_button.h:

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

#ifndef _Included_jni_VrpnButton
#define _Included_jni_VrpnButton
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_Button_initialize
 * Signature: (Ljava/lang/String;J)J
 */
JNIEXPORT jlong JNICALL Java_jni_VrpnButton_vrpn_1Button_1initialize
  (JNIEnv *, jobject, jstring, jlong);

/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_button_mainloop
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_jni_VrpnButton_vrpn_1button_1mainloop
  (JNIEnv *, jobject, jlong);

#ifdef __cplusplus
}
#endif
#endif

jni_vrpn_button.cpp:

#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

#include <jni_vrpn_button.h>
#include <vrpn_Button.h>
#include <vrpn_Connection.h>

/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_Button_initialize
 * Signature: (Ljava/lang/String;J)J
 */
JNIEXPORT jlong JNICALL Java_jni_VrpnButton_vrpn_1Button_1initialize
  (JNIEnv * env, jobject, jstring n, jlong conn)
{
 const char* name = strdup(env->GetStringUTFChars(n, 0));
 vrpn_Button_Example_Server * serv = new vrpn_Button_Example_Server(name, (vrpn_Connection *) conn, 1, 1.0);
 return (long) serv;
}

/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_button_mainloop
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_jni_VrpnButton_vrpn_1button_1mainloop
  (JNIEnv *, jobject, jlong ptr)
{
 ((vrpn_Button_Example_Server *) ptr)->mainloop();
}

有想法吗?

编辑:忘记发布错误:

$ $CRYSTAX/ndk-build 共享库: libjni_vrpn_button.so /cygdrive/c/开发/android-ndk-r4-windows-crystax-4/android-ndk-r4-crystax/sources/string/obj/l ocal/armeabi/objs/jni_vrpn_button/jni_vrpn_button.o: 功能中 Java_jni_VrpnButton_vrpn_1Button_1 初始化': /cygdrive/c/开发/android-ndk-r4-windows-crystax-4/android-ndk-r4-crystax/sources/string/jni/j ni_vrpn_button.cpp:18: 未定义 参考 vrpn_Button_Example_Server::vrpn_Button_Example_Serve r(char const*, vrpn_Connection*, int, double)'collect2: ld 返回 1 退出 状态品牌:*** [/cygdrive/c/Development/android-ndk-r4-windows-crystax-4/android-ndk-r4-crystax/sources/s tring/obj/local/armeabi/libjni_vrpn_button.so] 错误1

I'm trying to compile a C++ library (VRPN) with a couple of Java wrappers to be used in an Android app. Using the ndk-build command, I get an "undefined reference" error for the first line of my C++ interface file which references a constructor for an object in the library. I am fairly sure my code is correct - the call matches the method header and I have both the header and source files to verify that it is implemented. I think the problem is with my Android.mk file, which currently only references my single class. So the code appears to compile but won't link once it fails to find object code for the rest of the library. I'm pretty new to C++, so I don't know a lot about makefiles, but none of the "standard" makefiles I've seen match up to those used by the Android NDK, which apparently hide a lot of details. If I understand correctly, in a "standard" makefile, I simply name the output file and which object files it needs, followed by the object files and their source and header files, etc etc. I don't know how to force ndk-build to create object code for and link the rest of the library.

Here's my current Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jni_vrpn_button
LOCAL_SRC_FILES := jni_vrpn_button.cpp

include $(BUILD_SHARED_LIBRARY)

jni_vrpn_button.h:

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

#ifndef _Included_jni_VrpnButton
#define _Included_jni_VrpnButton
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_Button_initialize
 * Signature: (Ljava/lang/String;J)J
 */
JNIEXPORT jlong JNICALL Java_jni_VrpnButton_vrpn_1Button_1initialize
  (JNIEnv *, jobject, jstring, jlong);

/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_button_mainloop
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_jni_VrpnButton_vrpn_1button_1mainloop
  (JNIEnv *, jobject, jlong);

#ifdef __cplusplus
}
#endif
#endif

jni_vrpn_button.cpp:

#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

#include <jni_vrpn_button.h>
#include <vrpn_Button.h>
#include <vrpn_Connection.h>

/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_Button_initialize
 * Signature: (Ljava/lang/String;J)J
 */
JNIEXPORT jlong JNICALL Java_jni_VrpnButton_vrpn_1Button_1initialize
  (JNIEnv * env, jobject, jstring n, jlong conn)
{
 const char* name = strdup(env->GetStringUTFChars(n, 0));
 vrpn_Button_Example_Server * serv = new vrpn_Button_Example_Server(name, (vrpn_Connection *) conn, 1, 1.0);
 return (long) serv;
}

/*
 * Class:     jni_VrpnButton
 * Method:    vrpn_button_mainloop
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_jni_VrpnButton_vrpn_1button_1mainloop
  (JNIEnv *, jobject, jlong ptr)
{
 ((vrpn_Button_Example_Server *) ptr)->mainloop();
}

Ideas?

Edit: forgot to post the error:

$ $CRYSTAX/ndk-build SharedLibrary :
libjni_vrpn_button.so
/cygdrive/c/Development/android-ndk-r4-windows-crystax-4/android-ndk-r4-crystax/sources/string/obj/l
ocal/armeabi/objs/jni_vrpn_button/jni_vrpn_button.o:
In function
Java_jni_VrpnButton_vrpn_1Button_1
initialize':
/cygdrive/c/Development/android-ndk-r4-windows-crystax-4/android-ndk-r4-crystax/sources/string/jni/j
ni_vrpn_button.cpp:18: undefined
reference to
vrpn_Button_Example_Server::vrpn_Button_Example_Serve
r(char const*, vrpn_Connection*, int,
double)' collect2: ld returned 1 exit
status make: ***
[/cygdrive/c/Development/android-ndk-r4-windows-crystax-4/android-ndk-r4-crystax/sources/s
tring/obj/local/armeabi/libjni_vrpn_button.so]
Error 1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若能看破又如何 2024-10-01 09:26:11

我猜您忘记添加其他 cpp 文件,因此链接器无法找到符号。因此,将 vrpn_Button.cpp 和 vrpn_Connection.cpp 添加到您的 Android.mk 中:

LOCAL_SRC_FILES := \
    jni_vrpn_button.cpp \
    vrpn_Button.cpp \
    vrpn_Connection.cpp

这对于所有 makefile 都是相同的,即不限于 Android。

I guess you forgot to add the other cpp files, so the linker is not able to find the symbols. So add vrpn_Button.cpp and vrpn_Connection.cpp to your Android.mk:

LOCAL_SRC_FILES := \
    jni_vrpn_button.cpp \
    vrpn_Button.cpp \
    vrpn_Connection.cpp

It's the same for all makefiles, i.e. not limited to Android.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文