4

私のコードでは、OpenSSLヘッダーを次のような名前空間に取り込みます。

#include <cstdio>
namespace OpenSSL {
    #include <openssl/ssl.h>
    #include <openssl/err.h>
}

しかし、OpenSSLをサポートしているBoost ASIOを使用しているときに、これを実行しようとすると、爆発が発生する可能性があることを発見しましたが、OpenSSLシンボルをグローバル名前空間に取り込むように見えます。これについて何かできることはありますか、それともグローバル名前空間にすべてのOpenSSLライブラリのシンボルを残す必要がありますか?

ヘッダーを含めた後、問題のあるファイルで「using namespace OpenSSL」を試すことを考えましたが、残念ながら次のようなエラーが発生します。

/usr/include/openssl/x509v3.h:83:13: error: reference to ‘v3_ext_ctx’ is ambiguous
/usr/include/openssl/x509v3.h:71:8: error: candidates are: struct v3_ext_ctx
/usr/include/openssl/ossl_typ.h:160:16: error:                 struct OpenSSL::v3_ext_ctx

(OpenSSLはC ++ライブラリではなくCライブラリであるため、元の関数はC ++コンパイルユニットに取り込まれるまで名前空間に存在しないことに注意してください。私の手法は、Stroustrupの著書The C ++ Programming Language、 SpecialEditionで推奨されています。セクション9.5「アドバイス」から:「[8] グローバル名を避けるために名前空間にCヘッダーを含める;§8.2.9.1、§9.2.2。」

4

2 に答える 2

3

一般に、これは機能せず、機能しないはずです。Boost.Asioは、OpenSSLタイプをグローバル名前空間にあるものとして参照できることを期待できます(また、そうする必要があります)が、を参照する::buf_mem_stなどして失敗します。これは、として宣言されているため失敗しますOpenSSL::buf_mem_st

<openssl/ssl.h>また、別のヘッダーが含まれている場合はどうなりますか<stddef.h>(それはそうします)、それはとして定義size_tされOpenSSL::size_tます。includeを含む以降のコード<stddef.h>は、インクルードガードマクロがあるため、再びインクルードされません。また、::size_t誤って宣言されているため、プログラムで使用できなくなります。OpenSSL::size_t多くの実装では、opensslインクルードの後に​​インクルードすると、ほとんどのC++標準ライブラリが破損します。あなたの場合、とにかく<cstdio>含まれている可能性<stddef.h>がありますが、同じことが、OpenSSLヘッダーに含まれている標準(つまり、非OpenSSL)ヘッダーにも当てはまります<sys/types.h>。あなたのプログラムはOpenSSL::pid_tandOpenSSL::off_tなどを定義しますOpenSSL::timeval

この問題を修正する唯一の方法は、名前空間にインクルードする前にすべての標準Cヘッダーをインクルードすることです。これによりOpenSSL、そのヘッダーを再度インクルードしようとすると、グローバル名前空間にすでに正しくインクルードされています。それでも、OpenSSLを参照する他のヘッダー(Boost.Asioなど)が破損する可能性があります。

いやだっていうだけだよ。

于 2012-08-01T08:04:38.077 に答える
0

したがって、問題は次のように思われます。OpenSSLのシンボルは1回しか持ち込めません。それらの2番目の#includeは、インクルードガードのために効果がありません。つまり、コンパイルユニット内の1つの名前空間にのみ取り込むことができます。

したがって、コンパイルユニットでBoost.ASIOを使用する場合は、グローバル名前空間に含める必要があります(#include <boost /を実行する前に、自分でグローバル名前空間に取り込む必要があります)。 asio.hpp>または#include<boost/asio.hpp>にそれを実行させます。

于 2012-08-02T02:51:40.590 に答える