【问题标题】:Accessing other libraries from a JNI shared library - is it allowed?从 JNI 共享库访问其他库 - 是否允许?
【发布时间】:2014-03-16 03:03:36
【问题描述】:

我正在尝试开发一个在 STORM 框架上运行的应用程序,并使用 openCV 进行人脸识别。 首先,我用 maven(一个构建管理系统)创建了一个简单的项目,并用它运行了一个简单的 JNI 程序。但是,当我将它扩展为运行一个简单的 OpenCV 程序时,它可以正常编译,但会出现符号查找错误,这正是 JNI C++ 代码在 OpenCV 中创建 MAT 对象的时候。 这里是 Native 函数。

#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <jni.h>
#include <stdio.h>
#include "ie_agisoft_Test.h"
using namespace std;
using namespace cv;
JNIEXPORT void JNICALL Java_ie_agisoft_Test_hello(JNIEnv *, jobject) 
{
cout << "Hello World\n" << endl;
cout << "salmost there \n" <<endl;

Mat img = imread("Sairam.jpg");
imwrite("Saicopy.jpg", img);

    cout << "read the image \n"<<endl;
}

这是错误。 java:符号查找错误:/tmp/libagisoft6338470031759870366.so:未定义符号:_ZN2cv6imreadERKSsi

我正在使用 maven 构建系统来构建它,并且我有一个生成 .so 文件的生成文件,并将其保存在 target/classes 文件夹中。

任何人都可以解释为什么我的应用程序无法访问其他库,尽管编译和链接都很好?

这是完整的生成文件。

CC=gcc
CFLAGS= -c -Wall -fPIC -I/usr/lib/jvm/java-6-openjdk-amd64/include 
LDFLAGS=-fPIC -shared `pkg-config  opencv --cflags --libs`

SOURCES_DIR=src/main/c++
OBJECTS_DIR=target/c++
EXECUTABLE=target/classes/libagisoft.so

SOURCES=$(shell find '$(SOURCES_DIR)' -type f -name '*.cpp')
OBJECTS=$(SOURCES:$(SOURCES_DIR)/%.cpp=$(OBJECTS_DIR)/%.o)

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@

$(OBJECTS): $(SOURCES)
mkdir -p $(OBJECTS_DIR)
$(CC) $(CFLAGS) $< -o $@

clean:
rm -rf $(OBJECTS_DIR) $(EXECUTABLE)

提前致谢。请让我知道我是否可以提供更多详细信息以便为您提供清晰的图片。


这里是make文件输出

mkdir -p target/c++
gcc -c -Wall -fPIC -I/usr/lib/jvm/java-6-openjdk-amd64/include  src/main    
/c++/ie_agisoft_Test.cpp -o target/c++/ie_agisoft_Test.o
gcc -fPIC -shared -I/usr/local/include/opencv -I/usr/local/include  /usr/local   
/lib/libopencv_calib3d.so /usr/local/lib/libopencv_contrib.so /usr/local
/lib/libopencv_core.so /usr/local/lib/libopencv_features2d.so /usr/local
/lib/libopencv_flann.so /usr/local/lib/libopencv_gpu.so /usr/local
/lib/libopencv_highgui.so /usr/local/lib/libopencv_imgproc.so /usr/local
/lib/libopencv_legacy.so /usr/local/lib/libopencv_ml.so /usr/local
/lib/libopencv_nonfree.so /usr/local/lib/libopencv_objdetect.so /usr/local
/lib/libopencv_photo.so /usr/local/lib/libopencv_stitching.so /usr/local
/lib/libopencv_ts.so /usr/local/lib/libopencv_video.so /usr/local
/lib/libopencv_videostab.so   target/c++/ie_agisoft_Test.o -o target/classes/libagisoft.so

【问题讨论】:

  • 请提供完整的扩展命令行,由 make 执行以链接共享对象。我怀疑缺少 -lopencv 或类似的东西。 pkg-config opencv --cflags --libs 在你的系统上打印什么?
  • 你好 Matthias,我在上面的描述中添加了 makefile。谢谢
  • 另外,我有时会收到一个不同的错误,关于主 JNI 库本身,我假设有时,我的主 JNI 库也无法正确链接,这是我的错误获取..线程“main”中的异常 java.lang.UnsatisfiedLinkError: ie.agisoft.Test.hello()V at ie.agisoft.Test.hello(Native Method) at ie.agisoft.App.main(App.java: 11)

标签: java maven opencv java-native-interface shared-libraries


【解决方案1】:

反引号在 Makefile 中不起作用。请改用$(shell ...)

# LDFLAGS=-fPIC -shared `pkg-config opencv --cflags --libs` LDFLAGS=-fPIC -shared $(shell pkg-config opencv --cflags --libs) # 手动检查 LDFLAGS 的值 $(错误 $(LDFLAGS))

【讨论】:

  • 符号查找错误仍然存​​在。 java:符号查找错误:/tmp/libagisoft4557133975567625009.so:未定义符号:_ZN2cv6imreadERKSsi
  • 我将 makefile 的输出粘贴到单独的回复中。请检查以下答案。
  • @saipallavi,你在 Java 代码中有一个 System.loadLibrary("libagisoft") 调用,对吧? strace -eopen java ... 的输出是什么?
  • 是的,斯科特,我确实有 system.loadlibrary() 调用,事实上,它打印了我的 C++ 代码中的语句。当我从 opencv 定义 Mat 对象时,它无法循环/链接符号。另外,我在下面的单独评论中列出了我的 makefile 输出。我的链接错了吗?我应该链接 -lopencv 之类的东西吗?
  • 检查readelf -D libagisoft.sostrace -eopen java ...的输出,也试试LD_DEBUG=all java ...
【解决方案2】:

-l 选项必须在 .o 文件之后。只有那些满足目前遇到的未解决引用的指定库中的那些库被加载,这些库在目标文件之前是没有的。所以你应该把 $(LDFLAGS) 放在命令的末尾。

【讨论】:

  • 而且你不需要链接器命令行上的编译器标志,即 LDFLAGS=-fPIC -shared $(shell pkg-config opencv --libs) 就足够了。
  • 谢谢马蒂亚斯。它在 LDFLAGS 被放置在命令行末尾之后工作。
猜你喜欢
  • 2014-03-22
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 2013-01-14
  • 1970-01-01
相关资源
最近更新 更多