8

DLLを扱うのはこれが初めてです。MSDNのドキュメントに従って、プリプロセッサの定義に従ってマクロが定義されたヘッダーファイルfooExports.hを作成しました。

#ifdef FOODLL_EXPORTS
    #define FOO_API __declspec( dllexport )
#else
    #define FOO_API __declspec( dllimport )

私の意図は、DLL実装とコンソールアプリケーションの両方でこのヘッダーを使用することでした。これまでのところ、関数のインポートとエクスポートは問題なく機能します。エクスポートされた関数の1つのパラメーターとして必要な、定義済みの構造体をエクスポートしようとすると、問題が発生します。たとえば、前述のヘッダーファイルで宣言しFOO_API void foo( FooParams *args )args次のように定義された構造体です。

typedef struct FooParams
{
    char *a;
    char *b;
    void *whatever; //some other type
} FooParams;

この構造体は、fooExports.hではなくfoo.hで定義する必要があります。この構造体を元のヘッダーファイルから取り出さずにエクスポートする方法はありますか(エクスポート/インポートをfooExports.hに集中させたいことを考慮に入れて)。これを行うためのより良いアプローチは何でしょうか?DLLは、すべてCであり、それを使用するクライアントアプリケーションでもあります。

4

1 に答える 1

11

クライアントがこれまでに使用する唯一の用途が、FooParamsDLL関数から返されたクライアントへのポインターを取得し、それらのポインターを他のDLL関数に渡すことである場合は、それを「不透明(OPAQUE)型」にすることができます。

typedef struct FooParams FooParams;

fooExports.hで。マクロはそのFOO_API宣言に属していません。不透明(OPAQUE)型は、クライアントコードが次のことができないことを意味します。

  • タイプの変数を作成しますFooParams(ただし、問題ありませんFooParams * ptr = NULL;)。
  • の任意のメンバーで何でもしますFooParams
  • 検索sizeof(FooParams)-したがってmalloc、1つまたは複数のFooParamsオブジェクトを正しく配置できません。

#define上記のいずれかを実行するマクロをクライアントに表示することもできません。したがって、DLLには1つ以上の「コンストラクタ」または「ファクトリ」関数が必要です。

FOO_API FooParams* CreateFooParams(const char * input);

次のような一致する「デストラクタ」関数を定義することもお勧めします。

FOO_API void DestroyFooParams(FooParams * p);

定義がのように単純な場合でも{ free(p); }、DLL内で割り当てられたメモリがDLL外のコードによって解放されたり、その逆の場合に問題が発生することがあるためです(すべてのWindowsコードがとの同じ定義を使用するわけではないためmallocfree

これがすべて極端すぎる場合、他の唯一のオプションは、エクスポートされたヘッダーファイルにまたは定義を入れてクライアントに表示することです#include。それがないと、コンパイラがに何が含まれているのかわからないため、ポインタを渡す以外structに、に何かをしようとする試みは不可能になります。コンパイラ(リンカではなく)は、ライブラリやDLLからではなく、コマンドライン引数と-dファイルからのみ情報を取得します。FooParamsFooParams#include

于 2013-03-11T19:55:06.730 に答える