У меня следующая ситуация:
Я создал динамическую библиотеку lib.so. Эта библиотека использует другую статическую библиотеку lib.a. Они оба используют библиотеку Boost (я связываю их в файле CMake). (Я использую эту динамическую библиотеку в проекте Java)
Это код file.cpp в lib.so, который вызывает getFilesFromDirectory () из lib.a
#include "DrawingDetector.h"#include "../../DrawingDetection.h"#include <vector>
#include <boost/filesystem/operations.hpp>
using namespace std;
JNIEXPORT void JNICALL Java_DrawingDetector_detectImage( JNIEnv * env, jobject, jstring jMsg)
{
const char* msg = env->GetStringUTFChars(jMsg,0);
vector<File> filesPic = getFilesFromDirectory(msg,0);
env->ReleaseStringUTFChars(jMsg, msg);
}
Это код getFilesFromDirectory () из lib.a:
#include <string.h>
#include <iostream>
#include <boost/filesystem/operations.hpp>
#include "DrawingDetection.h"
using namespace std;
using namespace boost;
using namespace boost::filesystem;
vector<File> getFilesFromDirectory(string dir, int status)
{
vector<File> files;
path directoty = path(dir);
directory_iterator end;
if (!exists(directoty))
{
cout<<"There is no such directory or file!"<<endl;
}
for (directory_iterator itr(directoty); itr != end; ++itr)
{
if ( is_regular_file((*itr).path()))
{
//some code
}
}
return files;
}
Но когда мой проект вызывает библиотеку lib.so, возникает следующее сообщение:
java: symbol lookup error: /home/orlova/workspace/kmsearch/Images/branches/DrawingDetection/jni/bin/lib.so: undefined symbol:_ZN5boost11filesystem34path21wchar_t_codecvt_facetEv
Как я выяснил, он ломается в lib.a, когда пытается вызвать метод «path» boost.
Но я объявил все заголовки boost и связал их в файле CMake.
Можете ли вы объяснить, почему он не распознает методы повышения?
РЕДАКТИРОВАТЬ:
Версия моего компилятора gcc 4.6. И если я использую 4.5 все хорошо!
Также, если я использую некоторые методы boost непосредственно в file.cpp в lib.so, все работает нормально, например:
JNIEXPORT void JNICALL Java_DrawingDetector_detectImage( JNIEnv * env, jobject, jstring jMsg)
{
const char* msg = env->GetStringUTFChars(jMsg,0);
path directoty = path("/home/orlova");//if I use boost method here
vector<File> filesPic = getFilesFromDirectory(msg,0);// then everything works fine
env->ReleaseStringUTFChars(jMsg, msg);
}
НО
JNIEXPORT void JNICALL Java_DrawingDetector_detectImage( JNIEnv * env, jobject, jstring jMsg)
{
const char* msg = env->GetStringUTFChars(jMsg,0);
//path directoty = path("/home/orlova");//if I don't use boost method here
vector<File> filesPic = getFilesFromDirectory(msg,0);// then this method causes before-mentioned error!!
env->ReleaseStringUTFChars(jMsg, msg);
}
Как вы можете объяснить это поведение компилятора?
Обратите внимание, что ошибка возникает во время выполнения.
РЕШИТЬ
Проблема была в порядке библиотек в * target_link_libraries * в файле CMake.
НЕПРАВИЛЬНО:
find_library( LIBRARY_MAIN
NAMES lib.a
PATHS ../bin
)
set ( LIB_JNI
jpeg
${OpenCV_LIBS}
${BOOST_LIB}
${LIBRARY_MAIN}//static library is the last in the list of libraries and after boost!
)
target_link_libraries( ${PROJECT} ${LIB_JNI} )
ПРАВО:
find_library( LIBRARY_MAIN
NAMES lib.a
PATHS ../bin
)
set ( LIB_JNI
${LIBRARY_MAIN}
jpeg
${OpenCV_LIBS}
${BOOST_LIB}//boost library is the last in the list and after static library!
)
target_link_libraries( ${PROJECT} ${LIB_JNI} )
Кажется, что вы ссылку Boost.Filesystem
динамически — если это так, вы должны убедиться, что эта библиотека загружается. Вы можете сделать это, либо добавив его в LOCAL_LDLIBS
линия в Android.mk
или предварительно загрузив его вручную перед загрузкой lib.so
в коде Java.
В качестве альтернативы, просто связать Boost (и все остальное) статически lib.so
и забудьте обо всем этом динамическом беспорядке. 🙂
Update1: в отношении обновления, которое вы опубликовали — попробуйте поместить boost_filesystem.a в качестве прошлой объект в строке компоновщика.
Других решений пока нет …