none
VC++で実装したDLL内のイベントハンドラを登録する関数をVC#から呼ぶ場合 RRS feed

  • 質問

  • はじめまして。お世話になります。

    mkmarimoと申します。

     

    今回、プログラミングに関して自身で解決できない問題が発生してしまったので

    ここで質問させていただきます。

     

    ただ、私自身それほどプログラミング上級者ではないので、言っていることが

    訳わからないかもしれませんのでご了承ください。

     

    現在、[VC#(EXE) → VC++(DLL) → WIN32API] という関係のプログラムを作成しています。

    EXEとDLLは自分で実装しています。

     

    ここで、VC++(DLL)では、あるイベントハンドラ(Aと呼びます)と、

    そのイベントハンドラを登録する関数(Bと呼びます)を実装しています。

    で、C#からはBを呼んでいます。A内でWIN32APIを利用しています。

     

    ※それぞれの属性と戻り値の型は以下のとおりです。

      A・・・Public static LONG CALLBACK

      B・・・Public BOOL

     

    しかし、Bを呼んだタイミングでこのB内で0x00000005(アクセス違反)で

    アプリが落ちてしまいます。

     

    これについて、何か考えられる原因はありますでしょうか。

    手のつけようがなくなりご質問させていただきました。

     

    私自身の都合によりソースは公開できませんが、わかる範囲で結構ですので、

    ご回答よろしくお願いします。

    2007年8月7日 9:59

回答

  • その VC++ 製の DLL ってのはネイティブってことでいいんですかね?

    いずれにせよ、C++ のヘッダの該当部分と C# の呼び出し部分(C++ がネイティブなら DllImport の宣言文も)ぐらいは書いていただかないとコメントしづらいですが。

     

    ところで、アクセス違反って 0xC0000005 じゃないですっけ。

     

    2007年8月7日 10:23
  •  mkmarimo さんからの引用

                int hModule = LoadLibrary("XXXXX.dll"); // 自作のDLLです

                IntPtr ptr;

                ptr = GetProcAddress(hModule, "B");
                B func = (B)Marshal.GetDelegateForFunctionPointer(ptr, typeof(B));

                func(); // ここで落ちます。

     
    ロードしたモジュールを リリース したいという要望がないならば、
     
    [DllImport("XXXXX.dll")]
    private static extern bool func();
     
    で良いと思います。
     
    とりあえず、例外が発生しているのが func() の部分なのか、XXXX.dll の中なのかも調べたほうがいいでしょう。
    あとは、delegate B に UnmanagedFunctionPointerAttribute を付与しない場合の呼び出し規約とかを確認されたほうがいいかもしれません。(省略した場合は stdcall だったと思います
    2007年8月7日 14:34

すべての返信

  • その VC++ 製の DLL ってのはネイティブってことでいいんですかね?

    いずれにせよ、C++ のヘッダの該当部分と C# の呼び出し部分(C++ がネイティブなら DllImport の宣言文も)ぐらいは書いていただかないとコメントしづらいですが。

     

    ところで、アクセス違反って 0xC0000005 じゃないですっけ。

     

    2007年8月7日 10:23
  • Hongliangさん

     

    お世話になります。mkmarimoです。

     

    ご返信ありがとうございます。

     

    以下、追加で補足します。

     

    > その VC++ 製の DLL ってのはネイティブってことでいいんですかね?

     

    はい、ネイティブです。

     

    > いずれにせよ、C++ のヘッダの該当部分と C# の呼び出し部分(C++ がネイティブなら DllImport の宣言文も)ぐらいは書い> ていただかないとコメントしづらいですが。

     

    すみません。C++のヘッダの該当部分というのがよくわかりませんが、C#からのDLLの呼び出しは

    DllImportでKernel32.dllをインポートし、デリゲートにより実現しています。

    この方法をとったのはこれしかわからなかったからです。

    一部ソースを載せます。

     

    using System.Runtime.InteropServices;

     

    namespace XXXXXXXXXXXX
    {
        public delegate bool B();

        class Program
        {
            [DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
            public static extern int LoadLibrary(String lpFileName);

            [DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
            public static extern bool FreeLibrary(int hModule);

            [DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
            public static extern IntPtr GetProcAddress(int hModule, String lpProcName);

     

            static void Main(string[] args)
            {
                int hModule = LoadLibrary("XXXXX.dll"); // 自作のDLLです

                IntPtr ptr;

                ptr = GetProcAddress(hModule, "B");
                B func = (B)Marshal.GetDelegateForFunctionPointer(ptr, typeof(B));

                func(); // ここで落ちます。

     

            ・・・・・・・・・・・・・・・・・・・

            ・・・・・・・・・・・・・・・・・・・

     

    > ところで、アクセス違反って 0xC0000005 じゃないですっけ。

     

    そのようでした。見間違えました。

     

    以上、よろしくお願いします。

    2007年8月7日 10:45
  • 普通にその B ですか、そいつを DllImport するわけにはいかないんですかね。まあ本質ではないですが。

     

    ここに書かれたのを見る限り、C++ の関数がなにか変なことをしてるんでしょう。それ以上は何も推測できません。

    2007年8月7日 13:38
  •  mkmarimo さんからの引用

                int hModule = LoadLibrary("XXXXX.dll"); // 自作のDLLです

                IntPtr ptr;

                ptr = GetProcAddress(hModule, "B");
                B func = (B)Marshal.GetDelegateForFunctionPointer(ptr, typeof(B));

                func(); // ここで落ちます。

     
    ロードしたモジュールを リリース したいという要望がないならば、
     
    [DllImport("XXXXX.dll")]
    private static extern bool func();
     
    で良いと思います。
     
    とりあえず、例外が発生しているのが func() の部分なのか、XXXX.dll の中なのかも調べたほうがいいでしょう。
    あとは、delegate B に UnmanagedFunctionPointerAttribute を付与しない場合の呼び出し規約とかを確認されたほうがいいかもしれません。(省略した場合は stdcall だったと思います
    2007年8月7日 14:34
  • K.Takaokaさん

     

    ご回答ありがとうございます。mkmarimoです。

     

    DllImportを用いてプログラムを実装しなおしてみましたが、今度は別の例外で落ちてしまいました。

    内容は「0x7c812a5b でハンドルされていない例外が発生しました: 0xE0434F4D: 0xe0434f4d」で

    よく意味がわかりませんでした。

     

    例外が発生しているのは、前回、今回ともにXXXX.dll内のようです。

     

    そもそもVC++でDLLを作成するのも初めてですので、勉強しなおします。

     

    以上、ありがとうございました。

    2007年8月8日 1:01
  • 遅いレスなので投稿者は見ていないかもしれませんが・・。

     

    これって、単純に XXXX.dll を作成したプロジェクトでデバッグ実行すればすぐに解決しますよね。

    ソースも手元にあるようですし・・。

     

    方法はいろいろありますが、

    1)メニューから「プロジェクト」「プロパティー」の中の「構成プロパティー」「デバッグ」

    で コマンドで 実行するアプリケーションを指定して実行する。

     

    2)XXXX.dll をデバッグコンパイルしたときにできる .pdb ファイルを exe ファイルと同じ場所に配置する。

      exeファイルを起動する。

      Visual Studio から「デバッグ」「プロセスにアタッチする」で 上記の exe ファイルにアタッチする。

     エラーが発生する上記の pdb ファイルを生成したときに利用した ソースファイルを Visual Studio で開いて

     ブレークポイントを設定する。

     

    試してみてください。

    2007年8月16日 4:56