Crypto ++的未定义参考,尽管已链接并且可在其他项目中使用

时间:2018-11-18 15:53:07

标签: 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 ++字符串对其进行编译:{{1​​}}。但是,当我在我的项目中使用该函数时,函数定义如下:

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

我得到了大量对Crypto ++的未定义引用,例如:

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

我对简单测试有效时实际发生的事情一无所知。因此希望有人能提供帮助。

编辑: 已经尝试过: Undefined reference to symbol, even though the library is linked

1 个答案:

答案 0 :(得分:1)

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 ++归档文件中的内容。因此,compile and 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

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

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

如果您想变得非常漂亮,可以将其打印并退回:

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