以下の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++ からどのように呼び出す必要がありますか? 今のところ、悪が少ないと感じているのでキャストを使用しますが、もっと良い方法はありますか?