c++ - Crypto++ 的 undefined reference ,尽管它已链接并在其他项目中工作

标签 c++ crypto++

所以我试图创建一个包装函数来使用 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++ 的 undefined reference ,例如:

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++存档的内容。因此编译和链接命令可能应该如下所示:

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

在这种情况下,我什至建议使用静态链接,以避免 (1) 愚蠢的 Linux 路径问题; (2) 路径种植/注入(inject)游戏。所以也许是这样的:

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?


您可能想要更改此签名以获取常量引用:

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));

如果你想变得非常流畅,你可以打印它并返回它:

ChannelSwitch channels;
channels.AddRoute(new FileSink(std::cout));
channels.AddRoute(new StringSink(result));

HexEncoder encoder(new Redirector(channels));

现在,当您将数据插入到 encoder 中时,它将进行十六进制编码,然后发送到 std::coutstd::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 将具有 VectorSourceVectorSink。您将能够:

VectorSource(data, true, new HashFilter(hash, 
    new HexEncoder(new StringSink(result))));
return result;

另请参阅Pull Request 730 .

关于c++ - Crypto++ 的 undefined reference ,尽管它已链接并在其他项目中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53362739/

相关文章:

c++ - 如何防止数字出现在科学计数法中

c++ - 使用 AES 和 Crypto++ 加密解密单个 block

c++ - 如何初始化 RSA::PrivateKey?

c# - 发送C#AES加密字符串给CyptoPP C++程序解密

gcc - 使用Cygwin x86_64构建Crypto++ 5.6.2

c++ - 如何轻松应用Crypto++哈希函数?

c++ - 我这个抵押贷款公式做错了什么?

c++ - 如何在透明背景上绘制PNG?

c++ - 指向不同类成员函数的指针

c++ - srand 函数如何与时间函数交互?