c++ - JNI 共享库中的 undefined symbol ,可执行文件正在运行

标签 c++ c linker makefile java-native-interface

我在 C++ 方面确实没有经验,所以我希望这只是导致此错误的一个小错误。抱歉,帖子太长了,但我试图包含所有重要的细节。

所以这就是我正在尝试做的事情:我正在使用一个外部库,它以两个文件夹的形式出现,每个文件夹都有一个 makefile。我正在尝试使用一个额外的 cpp 文件和 .h 文件中的 JNI header 创建一个 JNI 库。

所以文件夹结构是这样的: -> libcds/src 带有创建 libcds.a 的 makefile
-> SSA2 带有创建 SSA.a 的 makefile
-> 带有我的 cpp 和 h 文件的 myFolder 以及一个应该创建库的 makefile

下面是不同的 makefile:

libcds/源代码:

CPP=g++

CPPFLAGS=-O9 -w -DNDEBUG 

INCL=-I../includes/

CODERS_DIR=coders
CODERS_OBJECTS=$(CODERS_DIR)/huff.o $(CODERS_DIR)/huffman_codes.o

STATIC_PERMUTATION_DIR=static_permutation
STATIC_PERMUTATION_OBJECTS=$(STATIC_PERMUTATION_DIR)/perm.o ...

STATIC_BITSEQUENCE_DIR=static_bitsequence
STATIC_BITSEQUENCE_OBJECTS=$(STATIC_BITSEQUENCE_DIR)/static_bitsequence.o ..

STATIC_SEQUENCE_DIR=static_sequence
STATIC_SEQUENCE_OBJECTS=$(STATIC_SEQUENCE_DIR)/static_sequence.o, ..., wt_coder.o

UTILS_DIR=utils
UTILS_OBJECTS=$(UTILS_DIR)/alphabet_mapper_none.o $(UTILS_DIR)/alphabet_mapper.o

%.o: %.cpp

$(CPP) $(CPPFLAGS) $(INCL) -c $< -o $@

all: lib 

lib: pre $(CODERS_OBJECTS) $(STATIC_BITSEQUENCE_OBJECTS) $(STATIC_SEQUENCE_OBJECTS) $(UTILS_OBJECTS) $(STATIC_PERMUTATION_OBJECTS)
    ar rcs ../lib/libcds.a $(CODERS_OBJECTS) $(STATIC_BITSEQUENCE_OBJECTS) $(STATIC_SEQUENCE_OBJECTS) $(UTILS_OBJECTS) $(STATIC_PERMUTATION_OBJECTS)

pre:
    cp basics.h ../includes/
    cp */*.h ../includes/

SSA2:

CC=g++

CFLAGS=-w -O9 -DNDEBUG -I../libcds/includes/
CODERS_DIR=../libcds/src/coders

CODERS_OBJECTS=$(CODERS_DIR)/huff.o $(CODERS_DIR)/huffman_codes.o

STATIC_BITSEQUENCE_DIR=../libcds/src/static_bitsequence

STATIC_BITSEQUENCE_OBJECTS=$(STATIC_BITSEQUENCE_DIR)/static_bitsequence.o ...

STATIC_SEQUENCE_DIR=../libcds/src/static_sequence

STATIC_SEQUENCE_OBJECTS=$(STATIC_SEQUENCE_DIR)/static_sequence.o ...

UTILS_DIR=../libcds/src/utils

UTILS_OBJECTS=$(UTILS_DIR)/alphabet_mapper_none.o $(UTILS_DIR)/alphabet_mapper.o

all: index

# pattern rule for all objects files

%.o: %.c *.h

    $(CC) -c $(CFLAGS) $< -o $@

%.o: %.cpp *.h

    $(CC) -c $(CFLAGS) $< -o $@

index: bitrankw32int.o bitarray.o  ds/ds.o ds/globals.o ds/helped.o ds/shallow.o ds/deep2.o ds/blind2.o SSA.o

    cp ../libcds/lib/libcds.a SSA.a

    ar rcs SSA.a SSA.o bitrankw32int.o bitarray.o ds/ds.o ds/globals.o ds/shallow.o ds/helped.o ds/deep2.o ds/blind2.o

我的生成文件:

CC=g++ -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux
LD_LIBRARY_PATH=./
JNI_NAME= indexlib

all: test

%.o: %.c *.h
    $(CC) -c $(CFLAGS) $< -o $@

test_index: 
    $(CC) run_queries.c -o testIndex SSA.a

test_index_lib: run_queries.o
    ld -shared -soname lib$(JNI_NAME).so -o lib$(JNI_NAME).so run_queries.o SSA.a -lc

可执行文件 testIndex 可以正常运行。 然而,生成的库无法由 Java 加载并显示错误消息:

undefined symbol: _ZNSt8ios_base4InitC1Ev

当我使用 nm 查找该符号时,我得到以下结果:

000131b0 W _ZN8wt_coderD2Ev
U _ZNKSt5ctypeIcE13_M_widen_initEv
U _ZNSo3putEc
U _ZNSo5flushEv
U _ZNSo9_M_insertImEERSoT_
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i
U _ZSt16__throw_bad_castv
U _ZSt4cout

And with --demangle it looks like this: 000131b0 W wt_coder::~wt_coder()
U std::ctype::_M_widen_init() const
U std::ostream::put(char)
U std::ostream::flush()
U std::ostream& std::ostream::_M_insert(unsigned long)
U std::ios_base::Init::Init()
U std::ios_base::Init::~Init()
U std::basic_ostream >& std::__ostream_insert

(std::basic_ostream >&, char const*, int) U std::__throw_bad_cast()
U std::cout

所以实际上这可能与 Linker error: undefined reference to `std::ctype<char>::_M_widen_init() 有关

最佳答案

我认为您没有链接到 C++ 标准库。您需要它,因为您链接到的库之一是 C++。

在第一种情况下(目标 test_index)一切正常,因为您正在使用 g++ 进行编译和链接,并且它将隐式链接到 libstdc++。在共享库的情况下,您正在链接 ld,它不会隐式链接 libstdc++。

您可以使用g++ 编译和链接共享库或使用-lstdc++ 显式添加libstdc++。两者都应该有效。

关于c++ - JNI 共享库中的 undefined symbol ,可执行文件正在运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15577557/

相关文章:

C++:file.seekg() 似乎没有返回当前位置

c++ - 寻找搜索的效率?算法。 C++

c++ - 为什么存在 decltype 时范围解析会失败?

比较C中不同字符串的两个字符

使用 popen 更改目录

c++ - Rust,如何使用 DLL 中的全局变量? C++ 等效项需要 __declspec(dllimport)

c - 链接不同文件夹的生成文件

c++ - 替换常量 : when to use static constexpr and inline constexpr?

c - 如何基于 C 代码创建转换图

linker - 将 Racket 程序链接到 Fortran 库