みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

C#でWin32 MFC DLLが呼び出せない

C#で以下のエラーが発生し、非常に困ってます。
色々とサイトを見たのですが、DLLが本当にないのでは?という意見が多かったです。
しかし、私の方はDLLファイルはbin->debugフォルダ , obj->debugフォルダ、System32に置いてます。

問題が分かる方、是非教えてください!

using System.Runtime.InteropServices;

namespace WindowsFormsApplication
{
public partial class Form1 : Form
{
[DllImport("Win32DLL_TEST.dll")]
private extern static int func(int x, int y);
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
int n = func3(5, 7);//ここでエラー!
}
}
}


エラー内容
'System.DllNotFoundException' のハンドルされていない例外が WindowsFormsApplication.exe で発生しました。

追加情報: DLL 'Win32DLL_TEST.dll' を読み込めません: 指定されたモジュールが見つかりません。 (HRESULT からの例外: 0x8007007E)

備考
DLLは自作のWin32 DLL です。
extern "C"{
__declspec(dllexport) int __cdecl func(int x, int y)
}
と宣言し、VC++のMFC dialog上では呼び出しを成功しています。

投稿日時 - 2014-10-02 19:46:18

QNo.8776572

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

8人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

作成中のCSのプロジェクトに MFC/非MFCのDLLとPDBを追加します

ファイル > 追加 > 既存の項目 で

追加したファイルのプロパティの 出力ディレクトリーへコピーを常にコピー(または新しい場合はコピー)
に設定します

これで CSのbin\debug にDLLファイルがコピーされます

MFC/非MFCで手順は変わりないと思いますよ …

投稿日時 - 2014-10-03 20:06:32

ANo.3

因みに、DLLを作った時に、Win32DLL_TEST.libも一緒に作成してある筈。

静的リンクでDLLを使う場合、上記のlibファイルを使用するようにプリプロセッサ命令で以下のように指示すると

#pragma comment(lib, "Win32DLL_TEST.lib")

リンカが自動的にDLLも一緒にリンクするようにプロジェクトが書き換えられるので、自分で「これもリンクして」と指示する必要は無い筈です。

要は

#pragma comment(lib, "Win32DLL_TEST.lib")

の1行をどっかに書き足せば、それですべてオッケー、と言う事です(静的リンクで済ますなら、です)

静的リンクなので「DLLを書き換えた場合はexeをリビルドする必要がある」と言うのを忘れないように。

投稿日時 - 2014-10-03 14:45:26

ANo.2

>[DllImport("Win32DLL_TEST.dll")]
> private extern static int func(int x, int y);

これだけじゃ、DLL内の関数は呼べない。

・暗黙的(静的)リンクをする場合

DLLの関数を__declspecl(dllimport)を付けて宣言する。

リンカに「このDLLも一緒にリンクして」と指示する必要がある(リンクし忘れると実行時に'System.DllNotFoundException'例外が起きる)

この場合、作成されるexeファイルにDLLの実体が取り込まれるので、後からDLLのみ変更する事はできない(後からWin32DLL_TEST.dllを変更しても、変更が反映されない。DLLを変更したら、exeをビルドし直さなければならない)

宣言したDLL関数は、そのまま呼び出せる。

・明示的(動的)リンクをする場合

DLLの関数を宣言しない。

LoadLibraryのAPI関数で、dllファイルを自分でロードしなければならない。

GetProcAddressのAPI関数で、関数のアドレスを自分で取得してから呼び出さなければならない。

DLLは、実行時に「プログラムから明示的にロードされる」ので、一緒にリンクする必要はない。

この場合、作成されるexeファイルにはDLLの実体は取り込まれないので、後でDLLを変更すると、変更したDLLが呼び出される(後からWin32DLL_TEST.dllを変更すると、変更が反映される。exeをビルドし直す必要はない)

---

質問者さんがしなければならない事は、

・DLLを「静的リンク」にするか「動的リンク」にするか選ぶ

・「静的リンク」を選んだ場合は、プロジェクトに「Win32DLL_TEST.dll」を追加し、ビルド時に一緒にリンクされるようにする。

・「動的リンク」を選んだ場合は、関数宣言を削除し、LoadLibraryとGetProcAddressを駆使して、自分でDLLをロードして、自分で関数アドレスを取得して、自前で関数を呼び出すようにする。

と言う作業です。

投稿日時 - 2014-10-03 14:33:45

ANo.1

System.DllNotFoundExceptionが発生しているのであれば

自作のDLLが C#のbin\debugフォルダーに無いのが原因でしょう …

1つのソリューションに C#とVCのプロジェクトがあるのであれば

C#は標準で そのソリューションフォルダー(またはプロジェクトフォルダー)のbin\debugがexeの出力先

VCは ソリューションフォルダーのdebugが出力先

となっているので確認してみましょう


また DLL側の関数が __cdeclであるならば DllImportの CallingConventionをCdeclに設定したほうがいいでしょう

投稿日時 - 2014-10-02 21:52:49

補足

アドバイス有難うございます。
フォルダ先にDLLがないか何回も確かめましたが、あります。
分かった事は、Win32(MFC無)のDLLを作成し、確認したところ
C#側では正常に動作しました。

Win32(MFC無)、Win32(MFC付)で違いがあるという事です。

この点について原因、改善点が分かる方、是非お教えて頂きたいです。

投稿日時 - 2014-10-03 08:54:51

あなたにオススメの質問