DLL関数を使ったプログラムを動かしたんですが、ERRORが解決できず
困っています。DLLを作成したのはいいのですが、それをLoadLibraryで読み込もうとしても指定したプロシージャが見つからないというエラーになるようです。使用している環境はVisual Studio.NET2003です。
以下はDLLのソースです。
// plug.c //
#include <windows.h>
#include <stdio.h>
__declspec(dllexport) void CALLBACK TestFunc()
{
printf("DLLのTestFunc()関数が実行されました。\n");
}
これをビルドするとplug.dllとplug.expとplug.libが作成されました。
そしてこれを使用したプログラムが
// stab.c //
#include <windows.h>
#include <stdio.h>
typedef void (*TestFunc)(void);
void main()
{
HMODULE hModule;
DWORD error;
TestFunc funcPointer;
hModule = LoadLibrary(TEXT("plug"));
error = GetLastError();//error値が127
funcPointer = (TestFunc)GetProcAddress(hModule,TEXT("TestFunc"));
funcPointer();
FreeLibrary(hModule);
getchar();
}
LoadLibrary関数を使用してアプリのメモリ空間にDLLを読み込もうとしているんですが、ここでハンドルが正確に渡されていないみたいなんです。どうしてこうなるのか分かりません。わかる方いらっしゃったらよろしくお願いします。
No.7ベストアンサー
- 回答日時:
このようなBBSで聞かれるよりは、
MSDNをご自分で調べられた方が遥かに
自分のためになると思いますが。。。
まず、モジュール名ですが、
LoadLibraryは第1パラメータでファイル名の拡張子を省略した場合、
既定の拡張子として「.DLL」が追加されます。
実行モジュールの取得に失敗した場合、
拡張エラー番号は126になります。
まずは今回の127というエラーが本当にLoadLibraryの後直ぐに
取得された拡張エラーなのかを教えてください。
#GetLastErrorは直前に実行した関数のエラーしか見れないので、
#タイミング的に書き換わっている可能性があります。
エラー的に127が返されたということは、
GetProcAddressのエラーである可能性が非常に高いです。
もしもGetProcAddress関数のエラーで返されたエラーならば、
DLL側がdefファイルを使用してビルドされていない可能性があります。
DEFファイルを使用しない場合、VC++はエクスポートする関数名を
修飾するためDLL側で用意した関数の関数名を指定するだけでは
アドレスを取得できません。
取得側はGetProcAddressに"_TestFunc@0"というような
修飾された「完全に明確な名前」を指定する必要があります。
#修飾子名はビルドするたびに異なる可能性があります。
これを回避する為の一番手っ取り早い方法は、
plug.defというファイルをプロジェクトに取り込み、
エクスポートする関数名を限定する方法があります。
--- plug.def -------------------------------
LIBRARY plug
EXPORTS
TestFunc @1
---ここまで----------------------------------
参考URL:http://msdn.microsoft.com/ja-jp/library/cc429241 …
この回答への補足
plug.def(モジュール定義)をプロジェクトに取り込んでTestFuncで実行したところERRORなく動作しました。defファイルを取り込んだお陰ですね。ありがとうございます。
しかし、GetLastError()で値を見てみると、値が127のままです。
何故こうなるのかはとても気になるのですが、一応は普通に動いています。
No.17
- 回答日時:
> しかし、GetLastError()で値を見てみると、値が127のままです。
>何故こうなるのかはとても気になるのですが、一応は普通に動いています。
GetLastErrorですが、これは直前の「エラー」に関しての取得です。
つまり、関数に成功した場合に0が返ってくることにはなっていないのです。
http://msdn.microsoft.com/ja-jp/library/cc428944 …
非常にわかりずらいのですが、特定の関数以外の関数は、成功した時にはSetLastErrorは呼ばないのです。ということは、それ以前の関数呼び出しでのエラーの値がそのまま残っているということです。
なので、GetLastErrorを見る前に、関数が成功したかどうかの判定をする必要があるのです。
No.16
- 回答日時:
> 解決策として『extern "C"』をつけることです。
No13でも書きましたが、
Cリンゲージで修飾子抑制が有効なのは
あくまでも呼び出し規約が、
デフォルトの「__cdecl」の場合です。
呼び出し規約が__stdcallなどの場合、
Cリンゲージ指定であったとしても、
エクスポート名は始まりに「_」、
終わりに「@パラメータバイト数」
というCの修飾が行われます。
今回に限ってはNo11さんが言っている通り、
DEFファイルを使用する以外にないと思います。
No.15
- 回答日時:
この回答への補足
参考URLありがとうございます。DLLに関しては、まだ勉強不足という事もあってか初歩的なことも分からないです。ただ、皆さんのお陰で解決しつつあるわけですし、そろそろこの問題を締め切ろうと思います。
補足日時:2008/12/03 11:19No.14
- 回答日時:
★アドバイス
・『plug.c』をC言語としてコンパイルするか、
C++としてコンパイルして DLL を作成するかで関数名が異なります。
C++ではオーバーロードという機能があるため関数名の末尾などに
勝手に一意の文字列が追加されます。
ネットで『マングリング』を検索するといろいろと情報が出てきます。
http://eternalwindows.jp/windevelop/dll/dll06.html
・解決策として『extern "C"』をつけることです。
DLLソースと使う側のソースでC言語か、C++かを統一させます。
矛盾があると『マングリング』によって見つかりません。注意。
// plug.c
#include <stdio.h>
#include <windows.h>
extern "C" __declspec(dllexport) void TestFunc()
{
printf("DLLのTestFunc()関数が実行されました。\n");
}
// stab.c
#include <stdio.h>
#include <windows.h>
extern "C"{
typedef void (*TestFunc)(void);
}
参考URL:http://eternalwindows.jp/windevelop/dll/dll06.html
この回答への補足
リンケージ指定をやろうとすると、エラーになります。
エラーは( errorC2059:構文エラー:'文字列' )です。
cファイルで記述しているからエラーがでるんじゃないかと思うのですが。
No.13
- 回答日時:
> VC++ではリンケージ指定ではエクスポート名が装飾されるのを
> 避けることは出来ません関数名のままエクスポートできるのは
> defファイルのみです、それ以外の方法はありません
呼び出し規約を変更するすることで、
defファイルを使用しなくても、
修飾子名をはずすことができる場合があります。
>No10さんのC関数名の修飾をはずす方法か、
と書きましたが、今回の質問者さんは 呼び出し規約を
CALLBACK としているのでデフォルトだと__stdcallの呼び出しと
なるのでdefファイルでしかエクスポートできないかもしれません。
ためしに、__stdcallでCリンゲージ指定を行うと、
エクスポート名は「_TestFunc@0」となりました。
ちなみにデフォルトの__cdeclの呼び出し規約では
エクスポート名は「TestFunc」となりました。
No.12
- 回答日時:
>その方法を試したところERRORが起きました。
起こったことはともかくどういう内容だったかが重要では?
リンゲージの差異によるエラーだと思うので、
No10さんのC関数名の修飾をはずす方法か、
DEFファイルを使用することで解決できると思います。
DEFファイルやC関数名修飾については以下を参照。
http://msdn.microsoft.com/ja-jp/library/d91k01sh …
No.11
- 回答日時:
VC++ではリンケージ指定ではエクスポート名が装飾されるのを避けることは出来ません
関数名のままエクスポートできるのはdefファイルのみです、それ以外の方法はありません
# 装飾名の所為で取得できてないのは最初から確定してるからLoadLibraryの事はもう考えるな
参考URL:http://msdn.microsoft.com/ja-jp/library/56h2zst2 …
No.10
- 回答日時:
> その方法を試したところERRORが起きました。
> cファイルだったからだと思うのですが。リンケージ指定はC++だと出来るんですけどね。
extern "C"{
__declspec(dllexport) void __cdecl TestFunc(void);
}
__declspec(dllexport) void __cdecl TestFunc(void)
{
printf("DLLのTestFunc()関数が実行されました。\n");
}
typedef void __cdecl (*TestFunc)(void);
だと、どうでしょうか?
No.9
- 回答日時:
>フルパスにしても同じことが起こりました。
>あと、hModuleに入った値ですが0x10000000です。
そのときGetLastError()の値は0 (この操作は正しく終了しました。)になっていたはずです。
LoadLibrary()が成功すればGetLastErrorは0になります。
パスの指定も原因のひとつだったという事が考えられます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
DLLをGetProcAddress()で実行できない。
C言語・C++・C#
-
AfxLoadLibrary関数で、DLLのハンドルが取得できない
C言語・C++・C#
-
2回目からはLoadLibrary()がcnpdsdk.dll"を読み込み失敗する。"
C言語・C++・C#
-
-
4
画面を強制的に再描画させる方法
C言語・C++・C#
-
5
DLLの暗黙リンクの調べ方
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
python エラー
-
エクセルのエラーメッセージ「4...
-
fortranでプログラムを実行する...
-
Excelのエラーで困ってます。
-
バッチからsqlplusの接続エラー...
-
Visual Studioのstrcpy_sについて
-
Arduinoに関する質問
-
ビルド失敗 指定されたファイ...
-
RightとLeft関数のライブ...
-
コンパイルできません。
-
sys/time.hのインクルードがで...
-
VB2008で定数に色の設定をした...
-
入れ子になっている構造体配列...
-
デバッグ中のエラーのことで教...
-
ステップ実行について
-
LPCWSTRとchar
-
【R8C/Tinyマイコン】エラーに...
-
error C3867 関数呼び出しには...
-
VC++でboolがエラーになる
-
Fortran コンパイルエラーについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
python エラー
-
エクセルのエラーメッセージ「4...
-
Excelのエラーで困ってます。
-
fortranでプログラムを実行する...
-
バッチからsqlplusの接続エラー...
-
適切な変換関数が存在しない???
-
VB2008で定数に色の設定をした...
-
HEWを使用しているのですが、こ...
-
sys/time.hのインクルードがで...
-
BC30002: 型 'ListItem' が定義...
-
Handlesについて
-
Visual Studioのstrcpy_sについて
-
RightとLeft関数のライブ...
-
error C3867 関数呼び出しには...
-
デバッグ中のエラーのことで教...
-
コンパイルできません。
-
multiple definitionというエラー
-
ビルド失敗 指定されたファイ...
-
レコードセットをcloseする所で...
-
左側がクラス、構造体、共用体...
おすすめ情報