2

以下のprototyで定義されたOpenSSLライブラリからこの関数を呼び出したい:

X509 *d2i_X509(X509 **px, const unsigned char **in, int len);

2 番目のパラメーターinが a として定義されているのは、次のconst unsigned char **理由によるものです。

  • d2i_X509 は、が指すバッファー内のデータを変更しません。*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

上記のコードは実際には単純化されているため、 p の型を に変更することはできませんconst unsigned char *。ポインターは、読み取りと書き込みの両方を実行する抽象 IO オブジェクトの背後に隠されています。以前の IO オブジェクトの良い点は、対称的な読み取りと書き込みコードを一緒に保持することです。私の IO オブジェクトで読み取りと書き込みに 2 つの別々のポインターを使用することは可能ですが、それを行うことの全体的な利点は非常に小さいです (マイナスではない場合)。多くの構文ノイズを追加します。また、何らかの外部の無関係な API 呼び出しによって強制された IO オブジェクトでのそのような深い内部変更を行うことは、非常にストレッチに見えます。

解決策は、キャストを実行するか、返されたポインター値をまったく使用しないことです (サイズパラメーターがあるため) が、どちらも適切ではありません。d2i_X509 のプロトタイプに十分な情報が含まれていないか、コンパイラの const チェック規則が厳しすぎるようです。

そのような API を C++ からどのように呼び出す必要がありますか? 今のところ、悪が少ないと感じているのでキャストを使用しますが、もっと良い方法はありますか?

4

1 に答える 1

1

まず、+=このコードの はあまり意味がありません。

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;
}
于 2012-09-07T16:47:17.677 に答える