代码之家  ›  专栏  ›  技术社区  ›  Lars Nielsen

Crypto++的未定义引用,尽管它已链接并在其他项目中工作[重复]

  •  2
  • Lars Nielsen  · 技术社区  · 7 年前

    因此,我正在尝试使用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

    1 回复  |  直到 7 年前
        1
  •  1
  •   jww avp    7 年前
    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?


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

    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::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 .