So-net無料ブログ作成

DLLでextern "C" でstdcall [プログラミング]

とあるソフトのプラグインを作る事にしました。
このプラグインは普通のDLLの拡張子を変更したものなので、普通にDLLを作ります。


DLLを作るには、Visual C++ならプロジェクト作成時にDLLを作る指定をするだけなので、何も問題ありません。

後は、普通にプログラムを書いて、外部に公開する関数に「_declspec(dllexport)」と付けるだけです。

_declspec(dllexport) void func()
{
    ....
}

これで、外部からDLL内のfunc関数を呼び出せるようになります。

ところが、C++の場合は関数のオーバーロード(引数が違えば同じ名前の関数を定義できる機能)がある所為で、内部では関数名が違う名前に置き換えられています。
ソースファイルにはfuncと書いてあるのに、実はfuncではないという事態になるのです。

DLLの場合、関数名を頼りにアクセスするので、これはちょっと困り者です。
置き換え後の名前でアクセスすれば良いのですが、名前の変換ルールは決まってないし、これは単なるC++の勝手な都合なので、他に押し付けることも出来ません。
C++が周りに合わせる必要があります。
そのために、「extern "C"」を付けます。

_declspec(dllexport) extern "C" void func()
{
    ....
}

これで、名前の置き換えは起こらなくなります。func関数はfunc関数として外部に公開されます。

普通にDLLを作るのなら、これでOK。


さて、

Windowsの都合なのかVisual C++の都合なのか知りませんが、Visual C++では、関数の呼び出し方法が2種類あります。
stdcall」と「cdecl」です。

詳しい違いはこの際どうでも良いので置いておくとして、重要なのは、関数の呼び出しは、関数の定義に合わせないといけないと言う事です。
stdcallとして作った関数はstdcallとして呼び出さないと、大変なことになります。

関数の呼び出し方法を指定するには、関数の戻り値の後ろに「__stdcall」か「__cdecl」を付ければOK。

void __stdcall func();

void __cdecl func();

実は、いま作ろうとしているプラグインは関数はstdcallとして呼び出す事になっています。
なので、関数の定義もstdcallとしなければなりません。

_declspec(dllexport) extern "C" void __stdcall func()
{
    ....
}

これで、問題は無いはずなのですが………。

__stdcallを付けると、extern "C"の指定がキャンセルされました。

なんですと~~~っ!

(正確には、extern "C"がキャンセルじゃなくて、stdcallが持つ名前の変換ルールに従って名前が置き換えられる)

一体どうすれば………。
C++を使うのを止めてCを使えと、そういうことか?


結論。

DEFファイル(拡張子がDEFのファイル)に、外部に公開する関数の名前を書いておけばOK

LIBRARY DLLの名前

EXPORTS
   公開する関数名

こうすると、_declspec(dllexport)の指定が不要になります。

extern "C" void __stdcall func()
{
    ....
}
[車(セダン)] 今日の一冊
ガリレオの指―現代科学を動かす10大理論

ガリレオの指―現代科学を動かす10大理論

  • 作者: ピーター アトキンス
  • 出版社/メーカー: 早川書房
  • 発売日: 2004/12
  • メディア: 単行本

タグ:VisualC++
nice!(0)  コメント(0)  トラックバック(1) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 1

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。