我正在尝试通过Java的Crypto ++包使用AES。因此,我的Java代码中有两个本机方法encrypt
和decrypt
,然后由C包装以访问C ++方法。
从命令行运行我的C ++程序,但通过JNI从Java调用它失败,出现undefined symbol
错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/yves/temp/lib/libCI3CppEncryptionTools.so: /home/yves/temp/lib/libCI3CppEncryptionTools.so: undefined symbol: _ZTIN8CryptoPP6FilterE
我正在通过以下方式进行编译:
g++ -c -Icryptopp562 -O3 -fwhole-program -fdata-sections -ffunction-sections -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp -Lcryptopp562 -lcryptopp
gcc -I${JAVA_HOME}/include -O3 -fwhole-program -fdata-sections -ffunction-sections -Wall -shared -fPIC -o libCI3CppEncryptionTools.so CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -Wl,--gc-sections
首先是C ++部分,然后与C包装器结合使用。 -fdata-sections
,-ffunction-sections
和-Wl,--gc-sections
是我试图删除死代码的原因,因为我认为JNI可能不喜欢未使用或未引用的代码。
我使用以下方法检查了符号是否未定义:
nm lib/libCI3CppEncryptionTools.so | grep _ZTIN8CryptoPP6FilterE
U _ZTIN8CryptoPP6FilterE
是的,确实如此。但为什么我的C ++命令行程序有效?检查这会产生相同的结果。
我也看了一下符号:
c++filt _ZTIN8CryptoPP6FilterE
typeinfo for CryptoPP::Filter
包含CryptoPP::Filter
的标头。我很好奇为什么在检查符号时会说U
。
有没有人知道什么可能导致问题或在哪里寻找解决问题?任何提示/见解都非常受欢迎!
答案 0 :(得分:1)
首先编译CI3CppEncryptionTools.c,然后将其.o链接到.so。您正在链接.c
编辑:通过以下方式将您的cryptocpp库静态链接到您的共享库:-Wl,--whole-archive libcryptocpp.a -Wl,--no-whole-archive
gcc -I${JAVA_HOME}/include -O3 -fwhole-program -fdata-sections -ffunction-sections -Wall -shared -fPIC -o libCI3CppEncryptionTools.so CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -Wl,--whole-archive libcryptocpp.a -Wl,--no-whole-archive -Wl,--gc-sections
答案 1 :(得分:0)
我总是忘记在第二步中链接Crypto ++库(实际上我是在第一步中完成的,这完全是胡说八道)。这两个命令编译库a-ok!
g++ -c -Icryptopp562 -O3 -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp
gcc -I${JAVA_HOME}/include -O3 -shared -fPIC -o libCI3CppEncryptionTools.so CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -lcryptopp