Search code examples
c++cjava-native-interfaceg++shared-libraries

How to link shared library to another shared library


I am trying to create shared library which is implementing JNI(Java Native Interface). My shared library is using another shared library which is named libPosAPI.so. But my shared library not correctly linking shared functions of libPosAPI.so.

In an implementation cpp, i am trying to use function vatps::PosAPI::sendData() of libPosAPI.so. Here is my build command:

g++ -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -I. -shared -o libPosAPIJni.so main_ubp_pos_PosAPIJni.cpp

It compiles successfully. Even it does not ask to provide libPosAPI.so with linker. But when use output shared library(libPosAPIJni.so), it gives following error undefined symbol: _ZN5vatps6PosAPI8sendDataB5cxx11Ev. I also provided libPosAPI.so with -L -l options. The result is same.

Here is my header file. That is a result of javac -h PosAPIJni.java.

main_ubp_pos_PosAPIJni.h

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

#ifndef _Included_main_ubp_pos_PosAPIJni
#define _Included_main_ubp_pos_PosAPIJni
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     main_ubp_pos_PosAPIJni
 * Method:    sendData
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_main_ubp_pos_PosAPIJni_sendData
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

main_ubp_pos_PosAPIJni.cpp

#include "main_ubp_pos_PosAPIJni.h"
#include "PosAPI.h" // header file of libPosAPI.so
#include <iostream>

using namespace std;

inline string jstring_to_string(JNIEnv* env, jstring string) {
    string value;
....
}

// IMPLEMENTATIONS
JNIEXPORT jstring JNICALL Java_main_ubp_pos_PosAPIJni_sendData(JNIEnv* env,
        jclass cls) {
    string res_sendData = vatps::PosAPI::sendData(); // The PROBLEM IS HERE!!. trying to use function of libPosAPI.so. declared in PosAPI.h

    return string_to_jstring(env, res_sendData);
}

The output of nm command of two shared libraries:

nm -D libPosAPI.so | grep sendData :

000000000000c3e0 T sendData
000000000000a8dc T _ZN5vatps6PosAPI8sendDataEv

nm -u libPosAPIJni.so | grep sendData:

U _ZN5vatps6PosAPI8sendDataB5cxx11Ev

Please direct me right way :)


Solution

  • Let's decode your symbol:

    $ c++filt _ZN5vatps6PosAPI8sendDataB5cxx11Ev
    vatps::PosAPI::sendData[abi:cxx11]()
    

    So, your code expects sendData with std::string with C++11 ABI, whereas libPosAPI.so provides sendData with pre-C++11 ABI std::string.

    abi:cxx11 hints to GCC5 and the C++11 ABI:

    Users that depend on third-party libraries or plugin interfaces that still use the old ABI can build their code with -D_GLIBCXX_USE_CXX11_ABI=0 and everything should work fine. In most cases, it will be obvious when this flag is needed because of errors from the linker complaining about unresolved symbols involving __cxx11.