找不到已编译的c++库函数

问题描述 投票:0回答:1

我有一个名为 libmylibrary.a 的文件和一个名为 mylibrary.h 的头文件 这包含一个名为 myfunction() 的函数。我将它们与 cpp 文件(HelloWorldJNI.cpp)组合起来,创建了一个名为 native.dll 的新库。但是,当我尝试使用 JNI 在 Java 中编译 native.dll 时,我无法找到 libmylibrary.a 和 mylibrary.h 中的函数。

mylibrary.h

// mylibrary.h
#ifndef MYLIBRARY_H
#define MYLIBRARY_H

#ifdef __cplusplus
extern "C" {
#endif

void myFunction();  // Declare the function prototype

#ifdef __cplusplus
}
#endif

#endif // MYLIBRARY_H

这些是我遵循的步骤
1.创建用于集成JNI的java文件(HelloWorldJNI.java)

public class HelloWorldJNI {
    static {
        System.load("/home/centos/test5/native.dll");
    }
    public static void main(String[] args) {
        new HelloWorldJNI().sayHello();
    }
  //native method with no body
  public native void sayHello();
}

2.使用此命令创建了 HelloWorldJNI.h 文件

javac -h .  HelloWorldJNI.java

3.将 mylibrary.h 文件和 HelloWorldJNI.h 文件与我的 cpp 文件(HelloWorldJNI.cpp)集成

#include<iostream>
#include<jni.h>
#include "mylibrary.h"
#include "HelloWorldJNI.h"
void sayHello(){
  myFunction();
}
int main() {
    sayHello();  // Call the function from the library

    return 0;
}
JNIEXPORT void JNICALL Java_HelloWorldJNI_sayHello
  (JNIEnv* env, jobject thisObject) {
    sayHello();
}

4.编译这些文件(创建.o文件)

g++ HelloWorldJNI.cpp -L. -lmylibrary -I"/home/centos/jdk-21.0.1/include" -I"/home/centos/jdk-21.0.1/include/linux" -o HelloWorldJNI.o

5.生成.o文件到.dll文件

g++ -shared -o native.dll HelloWorldJNI.o

6.编译并运行HelloWorldJNI.java

java HelloWorldJNI

出现此错误:

java: symbol lookup error: /home/centos/test5/native.dll: undefined symbol: myFunction

如何将 libmylibrary.a 合并到我的 Java 代码编译中以确保它识别 libmylibrary.a 中的函数?

PS:我确信 libmylibrary.a 没有问题,因为我能够使用纯 c++ 调用 myFunction() 但在使用 JNI 时似乎存在某种我无法弄清楚的链接问题

java c++ c java-native-interface
1个回答
1
投票

我尝试了您的所有步骤并进行了一些细微的更改,这对我有用。附上构建脚本:

JAVA_SDK_HOME=/home/user/lib/jdk-21.0.1

g++ -fPIC -c mylibrary.cpp -o mylibrary.o
ar rs mylibrary.a mylibrary.o

$JAVA_SDK_HOME/bin/javac -h . HelloWorldJNI.java

g++ -fPIC -shared -o native.dll HelloWorldJNI.cpp mylibrary.a \
  -I $JAVA_SDK_HOME/include/ \
  -I $JAVA_SDK_HOME/include/linux

不过有一些注意事项:

  1. 在 Windows 上,您很可能必须设置一些宏,因此
    JNIEXPORT
    实际上是
    __declspec(dllexport)
    ,而不是
    __declspec(dllimport)
  2. 要在 Linux 上链接
    *.so
    文件,您需要使用
    -fPIC
  3. 编译 C++ 文件
© www.soinside.com 2019 - 2024. All rights reserved.