サプライヤーのライブラリをC++アプリケーションと組み合わせて使用しようとしています。ライブラリの大部分はCに基づいています。これは通常extern "C"
オプションの問題ではありませんが、C++コンパイラが受け入れない問題に遭遇しました。
コードを次のサンプルファイルに単純化しました。 header.hは、suppierライブラリからのヘッダーを表し、main.c/cppは私自身のファイルです。私の実際のアプリケーションはC++アプリケーションなので、main.cppで動作するようにします。
header.h(u64 u64;
行に注意してください):
#ifndef HEADER_H
#define HEADER_H
#include <stdint.h>
typedef uint64_t u64;
union teststruct {
u64 u64;
struct {
u64 x:32;
u64 y:32;
} s;
};
#endif
main.c:
#include <stdio.h>
#include "header.h"
int main() {
union teststruct a;
a.u64=5;
printf("%x\n", a.u64);
return 0;
}
main.cpp(main.cと同じですが、余分なextern "C"
ステートメントがあります):
#include <stdio.h>
extern "C" {
#include "header.h"
}
int main() {
union teststruct a;
a.u64=5;
printf("%x\n", a.u64);
return 0;
}
次の行を使用してmain.cをコンパイルします
gcc -o test main.c
問題なくコンパイルします。ただし、コマンドでg ++コンパイラを使用してC++バージョンをコンパイルする
g++ -o test main.cpp
次のコンパイラエラーが発生します。
In file included from main.cpp:12:0:
header.h:11:9: error: ‘u64’ does not name a type
u64 x:32;
^
header.h:12:9: error: ‘u64’ does not name a type
u64 y:32;
^
問題は、サプライヤーが型と変数名の両方に同じ名前(u64)を使用したことです。これは、最初は悪い考えのように思えますが、gccは明らかにそれを受け入れます。ライブラリ(つまりheader.h)は非常に大きいため、これを変更したくありません。これはコード内で頻繁に発生し、ときどき更新されます。 g ++がこの組み合わせを受け入れるようにする方法、またはmain.cppを変更してコンパイルする方法はありますか?without header.hを変更しますか?
teststruct
は、C++のスコープを定義します。修飾ID teststruct::u64
を作成できます。そのため、名前ルックアップの言語規則はそのことを考慮しており、クラスおよびユニオンのメンバーが外部スコープの識別子を隠すことを許可しています。 u64 u64;
が導入されると、非修飾u64
はグローバル::u64
を参照できず、メンバーのみが参照できます。そして、メンバーは型ではありません。
Cでは、union teststruct
はスコープを定義しません。このフィールドはメンバーアクセスでのみ使用できるため、競合は発生しません。そのため、フィールドはファイルスコープタイプ識別子を隠す必要はありません。
私が知る限り、簡単に回避するためにあなたができることは何もありません。このライブラリ(完全に有効なCライブラリ)は、有効なC++ライブラリではありません。変数名としてnew
またはtry
を使用した場合と違いはありません。適応させる必要があります。
C++では違法なヘッダーファイルがあるため、C++としてコンパイルされたコードでは#include
できません。ライブラリヘッダーファイルに変更を加えることができない場合(たとえば、ライブラリのサプライヤーに苦情を申し立てるなど)、最も簡単なオプションは、ライブラリの周りにシンC++互換のラッパーを書くことです:
C++コードをCヘッダーから分離するには、Wrapper.h
とWrapper.c
を作成します。.h
はC++に含めるのに有効ですが、not include header.h
、およびライブラリの相互作用に必要なすべてのタイプと機能を提供します。次に、.c
で#include "header.h"
を実行し、すべての呼び出し(および型を安全に変換するために必要なこと)を実装できます。これは明らかにC++ではなくCとしてコンパイルする必要があります。
前述のCとC++の非互換性のみが原因である場合は、header.h
をプログラムでC++互換ヘッダーファイルに変換し、header.hpp
などの名前を付けることができます。そして、新しいバージョンを同じ方法で変換できます。
コンパイラエラーは、何をどこで変更する必要があるかをすべて示しています。
header.h:11:9: error: ‘u64’ does not name a type
header.h
;を開きます。::
を挿入します。does not name a type
エラーについて繰り返します。いくつかの文字列処理とそれが完了しました。
PS:CからC++へのコンバーターもそれを行うことができます。