0

C/C++ コードが混在する DLL を作成しています。エクスポートする関数の序数を指定したい。だから私はこのような.DEFファイルを作成しました

LIBRARY LEONMATH

EXPORTS

    sca_alloc   @1
    vec_alloc   @2
    mat_alloc   @3

    sca_free    @4
    vec_free    @5
    mat_free    @6

    ...

C++ 関数とクラス メソッドの序数も指定したいと思います。Dependency Walker を使用して、関数の破損した名前を .DEF ファイルに追加しようとしました。

    ??0CScalar@@QAE@XZ      @25
    ??0CScalar@@QAE@O@Z     @26
    ??0CScalar@@QAE@ABV0@@Z @27
    ??1CScalar@@QAE@XZ      @28

しかし、これは失敗しました。なぜこれが起こっているのでしょうか?


編集: kauppiは良い観察をしたので、質問にさらに情報を追加しています。

  • プラットフォーム: Windows (移植性には興味がありません)
  • コンパイラ: Microsoft の C++ コンパイラ (私は VS2005 を使用しています)
  • これを行う理由:序数を使用すると、C コードからエクスポートされた C++ 関数を呼び出せるという利点があります。
4

2 に答える 2

4

まあ、私は序数(いくつかの醜い、コンパイラ固有のもののように見えます)の経験はありませんが、C ++/Cコードを互換性のあるものにするのを手伝うことができます。

C ++で、ヘッダーファイルが次のようになっているとします。

class MyClass
{
    void foo(int);
    int bar(int);
    double bar(double);
    void baz(MyClass);
};

次の手順を実行することで、C互換にすることができます。

#ifdef __cplusplus
#define EXTERN_C extern "C"
// Class definition here; unchanged
#else
#define EXTERN_C
typedef struct MyClass MyClass;
#endif

EXTERN_C void MyClass_foo (MyClass*, int);
EXTERN_C int MyClass_bar_int (MyClass*, int);
EXTERN_C double MyClass_bar_double (MyClass*, double);
EXTERN_C void MyClass_baz (MyClass*, MyClass*);

C ++ソースファイルでは、次のextern "C"ように、目的のメンバー関数に渡すさまざまな関数を定義するだけです(これは1つだけで、残りは同様に機能します)。

extern "C" void MyClass_foo (MyClass* obj, int i)
{
  obj->foo(i);
}

この場合、コードはC ++コードをまったく変更せずにCインターフェイスを持ちます(ヘッダー内の宣言を除く。ただし、それらは別のファイル"myclass_c.h"などに移動することもできます)。extern "C"で宣言/定義されたすべての関数が壊されることはないので、それらに対して他の操作を簡単に行うことができます。また、MyClassのインスタンスを構築/破棄する関数も必要になるでしょう(もちろん、これにはnew/deleteを使用できます)。

于 2008-12-18T18:29:16.407 に答える
2

「序数を使用すると、エクスポートされた C++ 関数を C コードから呼び出すことができるという利点があります」とおっしゃいました。、これは間違っていると言って申し訳ありません。

C++ クラス メンバ関数には、実装固有のレジスタ/パラメータで渡される不可視のthis値を必要とする特別な呼び出し規約があります。また、渡すクラス インスタンスが必要ですが、これは C では実現できません。

私が知っているこれの唯一の 2 つの使用法は、DLL のより高速な動的リンクと、より小さなインポート テーブルです。依存関係ウォーカーを使用して、system32 ディレクトリの mfc70.dll を調べるだけです。

于 2008-12-18T18:48:08.193 に答える