出于学习目的,我使用 swig 和 cmake 创建了 java 动态库。我无法从我创建的同一个库中调用 java 中的函数。 swig 文档告诉我这是忘记编译 swig 包装器文件并将其链接到我的 native 库的结果,但我非常确定我是用 cmake build 做到的。
CMakeList.txt
cmake_minimum_required (VERSION 2.6)
FIND_PACKAGE(SWIG REQUIRED)
find_package(Java REQUIRED COMPONENTS Runtime Development)
find_package(JNI REQUIRED)
INCLUDE(${SWIG_USE_FILE})
set(JAVA ${java_include_path} )
INCLUDE_DIRECTORIES(${JAVA} ${JAVA}/win32)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET_SOURCE_FILES_PROPERTIES(hello.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(hello.i PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_MODULE(hello java hello.i hello.cpp)
SWIG_LINK_LIBRARIES(hello ${Java_LIBRARIES} ${JNI_LIBRARIES} ${CMAKE_CURRENT_SOURCE_DIR})
你好.cpp
#include "hello.hpp"
int adding(const int x, const int y)
{
return y + x;
}
你好.hpp
int adding(const int x, const int y);
你好我
%module hello
%{
#include "hello.hpp"
%}
int adding(const int x, const int y);
谁能告诉我在创建动态库时我做错了什么?谢谢你的帮助。
之所以知道这个是因为eclipse中有这个错误提示
Exception in thread "main" java.lang.UnsatisfiedLinkError: hello.helloJNI.adding(II)I
at hello.helloJNI.adding(Native Method)
at hello.hello.adding(hello.java:14)
at hello.Main.main(Main.java:14)
这与文档中讨论的是同一种错误消息。
最佳答案
错误消息中缺少的符号是 JNI 包装器的一部分,而不是库本身的一部分。
通常这意味着在第一次调用 SWIG 模块之前,您没有为 SWIG 模块的 native 部分调用 System.loadLibrary()
。您的 CMake 文件看起来已经正确链接了实现,所以这不是您从文档中提到的错误情况。
以及手动调用:
System.loadLibrary("hello"); // The name of your DLL here
在您的 main
方法中,当我以 Java 为目标时,我喜欢在我的 SWIG 接口(interface)文件中使用以下内容:
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("hello"); // The name of your DLL here
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}
这会导致 native 库在需要之前自动加载,这对 Java 程序员来说似乎是最自然的。
关于Java 不会调用使用 swig 创建的 .dll 中的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27628813/