C ++: передать указатель указателя на функцию - PullRequest
1 голос
/ 11 июня 2019

Я новичок в C ++ и пытаюсь интегрировать Openssl в мой проект.Некоторые функции здесь, например i2d_RSAPublicKey, получают unsigned char** в качестве второго аргумента и сохраняют в нем некоторые данные.Мне задавали подобный вопрос здесь:

Как управлять принципами C ++ с помощью C-совместимых библиотек и API

Но так как использование std::string и std::vector не делаетЗдесь мне пригодится, я решил задать еще один вопрос.

Так как std::string::c_str() возвращает const указатель строки, а std::vector::data() возвращает только указатель строки, они несовместимы с этой функцией.Кроме того, я не думаю, что манипулирование указателем строки для хранения данных в std::string или std::vector является хорошей идеей.

Поэтому мой вопрос заключается в том, какой тип данных использовать, чтобы не нарушать стандарт RAII и проходуказатель на указатель на функцию, которая будет хранить в нем некоторые данные?

1 Ответ

2 голосов
/ 11 июня 2019

std::unique_ptr может принимать пользовательское средство удаления, которое позволяет ему управлять памятью, выделенной OpenSSL. То, какая именно функция должна вызываться для очистки, зависит от того, какая функция выделяет ее, но для примера i2d_RSAPublicKey, который вы использовали в своем примере, она должна обернуть OPENSSL_free:

struct OpenSSLFree
{
    void operator()(void* ptr)
    {
        OPENSSL_free(ptr);
    }
};

template <typename T>
using OpenSSLPointer = std::unique_ptr<T, OpenSSLFree>;

OpenSSLPointer<unsigned char> EncodeRSAPublicKey(RSA* key)
{
    unsigned char* out = nullptr;
    int status = i2d_RSAPublicKey(key, &out);
    if (status < 0) {
        // handle error
    }
    return OpenSSLPointer<unsigned char>{out};
}

Буфер, содержащий закодированный ключ, будет очищен исключительным образом.


Вы также можете использовать std::vector<unsigned char> в этом случае. Вам придется вызывать i2d_RSAPublicKey дважды: один раз, чтобы получить требуемый размер буфера, и снова, чтобы фактически кодировать данные:

std::vector<unsigned char> EncodeRSAPublicKey(RSA* key)
{
    int len = i2d_RSAPublicKey(key, nullptr);
    if (len < 0) {
        // handle error
    }

    std::vector<unsigned char> outVec(len);
    unsigned char* outPtr = outVec.data();
    len = i2d_RSAPublicKey(key, &outPtr);
    if (len < 0) {
        // handle error
    }

    return outVec;
}

Это, вероятно, более чистый интерфейс, но он не будет работать везде. std::unique_ptr с пользовательским подходом к удалению широко применяется, но, опять же, функция, вызываемая средством удаления, будет зависеть от того, как распределена память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...