Я хочу вызвать эту функцию из библиотеки OpenSSL, определенной с помощью прототипа ниже:
X509 *d2i_X509(X509 **px, const unsigned char **in, int len);
Второй параметр in
определяется как const unsigned char **
так как:
*in
*in
будет увеличен на количество данных, проанализированных из буфера.Теперь этот прототип представляет собой проблему, потому что, насколько я вижу, функцию нельзя вызывать следующим образом, который, насколько я понимаю, является нормальным способом вызова API (код управления ошибками удален, чтобы упростить задачу):
unsigned char buffer[2048];
unsigned char * end = buffer;
unsigned char * p = buffer;
end += read(fd, p, 2048);
certlen1 = parseint(&p);
X509 * cert1 = d2i_x509(NULL, &p, certlen1);
certlen2 = parseint(&p);
X509 * cert2 = d2i_x509(NULL, &p, certlen2);
Если я пытаюсь скомпилировать приведенный выше код, он говорит:
error: invalid conversion from 'unsigned char**' to 'const unsigned char**'
Я понимаю обоснование сообщения (объяснил Вот например), но в данном конкретном случае это обоснование не применяется, так как функция состояния в своей документации, она будет только увеличивать значение *in
Никогда не назначайте на него не связанный указатель.
Я не могу изменить тип р на const unsigned char *
Поскольку приведенный выше код на самом деле упрощен, указатель скрыт за каким-то абстрактным объектом ввода-вывода, выполняющим как чтение, так и запись. Хорошим моментом с предыдущим объектом ввода-вывода является то, что он поддерживает симметричное чтение и запись кода вместе, можно использовать два отдельных указателя для чтения и записи в моем объекте ввода-вывода, но общее преимущество от этого действительно мало (если не отрицательно) и добавить много синтаксического шума. Подобные глубокие внутренние изменения в объекте ввода-вывода, вызванные каким-либо внешним несвязанным вызовом API, выглядят действительно растянутыми.
Решением может быть выполнение приведения или даже вообще не использовать возвращаемое значение указателя (так как у меня есть параметр размера), но это тоже не так. Похоже, что прототип d2i_X509 не содержит достаточно информации, или что правило проверки констант компилятора в этом случае слишком строгое.
Как вызвать такой API из C ++? Пока я просто буду использовать актерский состав, поскольку я чувствую, что это меньшее зло, но есть ли лучший способ?
Во-первых, +=
в этом коде нет особого смысла:
p += read(fd, p, 2048);
Вы модифицируете p
В точку только что прошел данные, которые вы только что прочитали, так d2i_x509
буду читать барахло.
Я бы сделал это так:
unsigned char buffer[2048];
int n = read(fd, buffer, 2048);
if (n < 0) ..error..;
const unsigned char * p = buffer;
X509 * cert1 = d2i_x509(NULL, &p, certlen1);
X509 * cert2 = d2i_x509(NULL, &p, certlen2);
int used = p - buffer; // # of bytes actually parsed by the two calls
Любые будущие изменения могут быть сделаны в buffer
непосредственно.
Редактировать:
Хорошо, тогда замените это:
X509 * cert1 = d2i_x509(NULL, &p, certlen1);
с этим:
{
const unsigned char *q = p;
X509 * cert1 = d2i_x509(NULL, &q, certlen1);
p += q - p;
}
Других решений пока нет …