1

次のコードは、私が遭遇した状況を説明しています。

#ifdef __cplusplus
namespace ns
{
class pod
{
    const short foo;
    const char bar;
public:
    pod(short f,char b):foo(f),bar(b){}
    char foobar();
};
}
#else
typedef struct pod pod;
#endif


#ifdef __cplusplus
extern "C"{
#endif

extern pod* pod_new(short f, char b);//BANG!!!
extern char pod_foobar(pod* p); //BANG!!!

#ifdef __cplusplus
}
#endif

C リンケージ関数を名前空間内に配置できないnsか、C クライアントがそれらの定義を見つけられません。それらを名前空間から引き出すと、C++ 定義もコンパイルされません。これはすべて、C++ FAQ Litepodから学んだ解決策のためです。これはプリプロセッサのトリックにすぎません。そして悲しいことに、このトリックは名前空間を扱うことができませんでした。

私はどうしたらいいですか?タイプセーフをすべて破棄pod*してに置き換えるvoid*必要がありますか、またはこのような状況に対するより良い解決策はありますか? 何かアドバイスはありますか?お願いします!

4

2 に答える 2

3

関数に対して2つの異なる宣言を与えるだけです

C ++の場合:

extern "C" ns::pod* pod_new(short f, char b);
extern "C" char pod_foobar(ns::pod* p);

およびCの場合:

typedef struct pod pod;
extern pod* pod_new(short f, char b);
extern char pod_foobar(pod* p);

しかし、これで満足できない場合は、C++の場合はtypedef

typedef ns::pod ns_pod;

Cの場合

typedef struct ns_pod ns_pod;

次に、同じ共通関数プロトタイプを作成します。

extern ns_pod* pod_new(short f, char b);
extern char pod_foobar(ns_pod* p);

編集: Cでは、struct podまたはstruct ns_podは不完全なタイプであるため、Cでは、フィールドを使用したり、そのサイズを要求したりすることはできません。不完全な型へのポインタとaの違いは、そのようなポインタは同じ不完全な型の別のポインタにvoid*しか割り当てることができないということです。structstruct

typedef struct ns_pod2 pod2;
ns_pod* q = pod_new(...);   // valid
ns_pod2* r = pod_new(...);  // a constraint violation! (= compiler error)

あなたが主張したいのであれば、2番目のものは明示的なキャストが必要になります。これが、多くのCプログラマーがキャストを嫌う理由の1つです。

于 2012-09-22T12:08:18.077 に答える
1

私は自分でそれを理解しました:) objファイルのシンボルをnm.

C++ 名前空間は C リンケージを持つ関数には影響しないことが判明したため、上記のコードを次のように書き直すことができます。

#ifdef __cplusplus
namespace ns
{
class pod
{
    const short foo;
    const char bar;
public:
    pod(short f,char b):foo(f),bar(b){}
    char foobar();
};
}


#else
typedef struct pod pod;
#endif 


#ifdef __cplusplus
namespace ns{
extern "C"{
#endif

pod* pod_new(short f, char b);
char pod_foobar(pod* p);
void pod_free(pod* p);

#ifdef __cplusplus
}
}
#endif
于 2012-09-22T12:59:41.980 に答える