Crypto++ 的未定义引用,尽管它已链接并在其他项目中工作
Undefined reference for Crypto++ though it is linked and works in other projects
所以我正在尝试使用 Cryptop++ 创建一个用于生成散列的包装函数
我创建了这个测试函数:
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/cryptlib.h>
#include <vector>
#include <cstdint>
#include <string>
#include <iostream>
void test2()
{
CryptoPP::SHA1 hash;
CryptoPP::byte digest[CryptoPP::SHA1::DIGESTSIZE];
std::vector<uint8_t> v;
for (uint32_t i = 0; i < 1000; ++i)
{
v.push_back(i % 9);
}
hash.CalculateDigest(digest, v.data(), v.size());
CryptoPP::HexEncoder encoder;
std::string output;
encoder.Attach(new CryptoPP::StringSink(output));
encoder.Put(digest, sizeof(digest));
encoder.MessageEnd();
std::cout << output << std::endl;
}
并使用以下 clang++ 字符串对其进行编译:clang++ main2.cpp -lcryptopp
。但是,当我在我的项目中使用它时,函数定义如下:
template<typename Hash>
std::string get_hash(std::vector<uint8_t> data)
{
Hash hash;
// Intialise a byte "array" with space enough for the result
CryptoPP::byte digest[Hash::DIGESTSIZE];
// Create hash for the data
hash.CalculateDigest(digest, data.data(), data.size());
CryptoPP::HexEncoder encoder;
// result will hold the hex representation of the hash
std::string result;
// Tell the Hex encoder that result is the destination
// for its operations
encoder.Attach(new CryptoPP::StringSink(result));
encoder.Put(digest, sizeof(digest));
// As we will not put more in the message we end it
encoder.MessageEnd();
return result;
}
并像这样调用它:hash::get_hash<CryptoPP::SHA1>(pair.pivot);
使用以下编译器命令:clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread -lpqxx -lpq -lcryptopp examples/sql_index_example/sql_index_example.cpp.1.o -o/home/tools/git/alexandria/build/examples/sql_index_example/sql_index_example -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
我收到大量未定义的 Crypto++ 引用,例如:
examples/sql_index_example/sql_index_example.cpp.1.o: In function `alexandria::data::hash::GetHash[abi:cxx11](std::vector<unsigned char, std::allocator<unsigned char> >)':
sql_index_example.cpp:(.text+0x197): undefined reference to `CryptoPP::StringSinkTemplate<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::StringSinkTemplate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
我完全不知道当简单测试起作用时实际发生了什么。所以希望有人能帮忙。
编辑:
已经尝试过:
Undefined reference to symbol, even though the library is linked
clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread -lpqxx -lpq -lcryptopp \
examples/sql_index_example/sql_index_example.cpp.1.o -o/home/tools/git/alexandria/
build/examples/sql_index_example/sql_index_example -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
并且:
examples/sql_index_example/sql_index_example.cpp.1.o: In function `alexandria::data::hash::
GetHash[abi:cxx11](std::vector<unsigned char, std::allocator<unsigned char> >)':
sql_index_example.cpp:(.text+0x197): undefined reference to ...
重申@HolyBlackCat 所说的,-lcryptopp
需要跟在 sql_index_example.cpp.o
之后,因为 sql 目标文件需要 Crypto++ 存档中的内容。所以编译和 link 命令可能看起来像这样:
clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread \
examples/sql_index_example/sql_index_example.cpp.1.o \
-o /home/tools/git/.../sql_index_example \
-lpqxx -lpq -lcryptopp -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
在这种情况下,我什至建议静态 linking 以避免 (1) 愚蠢的 Linux 路径问题;和 (2) 路径 planting/injection 游戏。所以也许是这样的:
clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread \
examples/sql_index_example/sql_index_example.cpp.1.o \
/usr/local/lib/libcryptopp.a \
-o /home/tools/git/.../sql_index_example \
-lpqxx -lpq -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
另见 Why does the order in which libraries are linked sometimes cause errors in GCC?
您可能想要更改此签名以采用 const 引用:
std::string get_hash(const std::vector<uint8_t>& data);
这里不需要深拷贝。引用或指针就可以了。引用不能是 NULL
,因此它们更容易处理。
另见 When to use const and const reference in function args? How to pass objects to functions in C++? 有更多现代信息,包括 C++11。
对此:
HexEncoder encoder;
// result will hold the hex representation of the hash
std::string result;
// Tell the Hex encoder that result is the destination
// for its operations
encoder.Attach(new StringSink(result));
您可以将其压缩为:
std::string result;
HexEncoder encoder(new StringSink(result));
由于您要打印到 std::cout
,您甚至可以:
std::string result;
HexEncoder encoder(new FileSink(std::cout));
如果你想变得非常圆滑,你可以同时打印它和return它:
ChannelSwitch channels;
channels.AddRoute(new FileSink(std::cout));
channels.AddRoute(new StringSink(result));
HexEncoder encoder(new Redirector(channels));
现在,当您将数据插入 encoder
时,它将被十六进制编码,然后发送到 std::cout
和 std::string
。
关于:
std::vector<uint8_t> data;
...
HexEncoder encoder;
encoder.Attach(new CryptoPP::StringSink(result));
encoder.Put(digest, sizeof(digest));
// As we will not put more in the message we end it
encoder.MessageEnd();
Crypto++ 8.0 将有一个 VectorSource
和 VectorSink
。您将能够:
VectorSource(data, true, new HashFilter(hash,
new HexEncoder(new StringSink(result))));
return result;
另见 Pull Request 730。
所以我正在尝试使用 Cryptop++ 创建一个用于生成散列的包装函数 我创建了这个测试函数:
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/cryptlib.h>
#include <vector>
#include <cstdint>
#include <string>
#include <iostream>
void test2()
{
CryptoPP::SHA1 hash;
CryptoPP::byte digest[CryptoPP::SHA1::DIGESTSIZE];
std::vector<uint8_t> v;
for (uint32_t i = 0; i < 1000; ++i)
{
v.push_back(i % 9);
}
hash.CalculateDigest(digest, v.data(), v.size());
CryptoPP::HexEncoder encoder;
std::string output;
encoder.Attach(new CryptoPP::StringSink(output));
encoder.Put(digest, sizeof(digest));
encoder.MessageEnd();
std::cout << output << std::endl;
}
并使用以下 clang++ 字符串对其进行编译:clang++ main2.cpp -lcryptopp
。但是,当我在我的项目中使用它时,函数定义如下:
template<typename Hash>
std::string get_hash(std::vector<uint8_t> data)
{
Hash hash;
// Intialise a byte "array" with space enough for the result
CryptoPP::byte digest[Hash::DIGESTSIZE];
// Create hash for the data
hash.CalculateDigest(digest, data.data(), data.size());
CryptoPP::HexEncoder encoder;
// result will hold the hex representation of the hash
std::string result;
// Tell the Hex encoder that result is the destination
// for its operations
encoder.Attach(new CryptoPP::StringSink(result));
encoder.Put(digest, sizeof(digest));
// As we will not put more in the message we end it
encoder.MessageEnd();
return result;
}
并像这样调用它:hash::get_hash<CryptoPP::SHA1>(pair.pivot);
使用以下编译器命令:clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread -lpqxx -lpq -lcryptopp examples/sql_index_example/sql_index_example.cpp.1.o -o/home/tools/git/alexandria/build/examples/sql_index_example/sql_index_example -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
我收到大量未定义的 Crypto++ 引用,例如:
examples/sql_index_example/sql_index_example.cpp.1.o: In function `alexandria::data::hash::GetHash[abi:cxx11](std::vector<unsigned char, std::allocator<unsigned char> >)':
sql_index_example.cpp:(.text+0x197): undefined reference to `CryptoPP::StringSinkTemplate<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::StringSinkTemplate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
我完全不知道当简单测试起作用时实际发生了什么。所以希望有人能帮忙。
编辑: 已经尝试过: Undefined reference to symbol, even though the library is linked
clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread -lpqxx -lpq -lcryptopp \
examples/sql_index_example/sql_index_example.cpp.1.o -o/home/tools/git/alexandria/
build/examples/sql_index_example/sql_index_example -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
并且:
examples/sql_index_example/sql_index_example.cpp.1.o: In function `alexandria::data::hash::
GetHash[abi:cxx11](std::vector<unsigned char, std::allocator<unsigned char> >)':
sql_index_example.cpp:(.text+0x197): undefined reference to ...
重申@HolyBlackCat 所说的,-lcryptopp
需要跟在 sql_index_example.cpp.o
之后,因为 sql 目标文件需要 Crypto++ 存档中的内容。所以编译和 link 命令可能看起来像这样:
clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread \
examples/sql_index_example/sql_index_example.cpp.1.o \
-o /home/tools/git/.../sql_index_example \
-lpqxx -lpq -lcryptopp -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
在这种情况下,我什至建议静态 linking 以避免 (1) 愚蠢的 Linux 路径问题;和 (2) 路径 planting/injection 游戏。所以也许是这样的:
clang++ -std=c++17 -Wall -Werror -Wextra -pthread -pthread \
examples/sql_index_example/sql_index_example.cpp.1.o \
/usr/local/lib/libcryptopp.a \
-o /home/tools/git/.../sql_index_example \
-lpqxx -lpq -Wl-Bstatic -L. -lalexandria -Wl-Bdynamic
另见 Why does the order in which libraries are linked sometimes cause errors in GCC?
您可能想要更改此签名以采用 const 引用:
std::string get_hash(const std::vector<uint8_t>& data);
这里不需要深拷贝。引用或指针就可以了。引用不能是 NULL
,因此它们更容易处理。
另见 When to use const and const reference in function args? How to pass objects to functions in C++? 有更多现代信息,包括 C++11。
对此:
HexEncoder encoder;
// result will hold the hex representation of the hash
std::string result;
// Tell the Hex encoder that result is the destination
// for its operations
encoder.Attach(new StringSink(result));
您可以将其压缩为:
std::string result;
HexEncoder encoder(new StringSink(result));
由于您要打印到 std::cout
,您甚至可以:
std::string result;
HexEncoder encoder(new FileSink(std::cout));
如果你想变得非常圆滑,你可以同时打印它和return它:
ChannelSwitch channels;
channels.AddRoute(new FileSink(std::cout));
channels.AddRoute(new StringSink(result));
HexEncoder encoder(new Redirector(channels));
现在,当您将数据插入 encoder
时,它将被十六进制编码,然后发送到 std::cout
和 std::string
。
关于:
std::vector<uint8_t> data;
...
HexEncoder encoder;
encoder.Attach(new CryptoPP::StringSink(result));
encoder.Put(digest, sizeof(digest));
// As we will not put more in the message we end it
encoder.MessageEnd();
Crypto++ 8.0 将有一个 VectorSource
和 VectorSink
。您将能够:
VectorSource(data, true, new HashFilter(hash,
new HexEncoder(new StringSink(result))));
return result;
另见 Pull Request 730。