• 締切済み

C++/CLIからC++の呼び出しで例外

お世話になります。 C#からC++のNativeコード(unmanaged)を呼び出したいと思い、C++/CLIでラッパーを作りました。 そのラッパーのクラス内で、C++で書かれたNativeコードのクラスのインスタンスを作成する時に例外が発生してしまいます。 例外はこんな感じです。 System.Runtime.InteropServices.SEHException はハンドルされませんでした。 Message="外部コンポーネントが例外をスローしました。" Source="ManMovLib" ErrorCode=-2147467259(0x80004005) StackTrace: 場所 new(UInt32 ) C++/CLIは以下の様なコードで、コンストラクタ内でC++のクラスの実体を作っています。そして、このnewで例外が発生します。 AVSource::AVSource(void) {   m_pObj = new CAVSource; } C++側は、実は何もしていません。 CAVSource::CAVSource(void) { } そして、色々と試行錯誤をした結果、C++側のクラスにvirtual関数があると、例外が出てしまうという事実を突き止めました。 ただ、どこを調べても、virtual関数を用いてはいけないとは書いてありません。 実際、virtualを使ってはいけないという制約があるのでしょうか? また、何かNativeのコードを作成する際に注意点とかありますでしょうか? ちなみに、プロジェクトの設定で、Nativeコードのデバッグを可能にするチェックをつけてデバッグ実行すると、何故かこの例外は発生せずに、全て正常に動きます。これもなぞです。 よろしくお願いします。

みんなの回答

  • oldman50
  • ベストアンサー率29% (8/27)
回答No.2

http://www.codeproject.com/KB/mcpp/quickcppcli.aspx#A8 が参考になれば幸いです。 5. Make sure you delete the native pointer in the destructor of the managed class. とか。 http://www.amazon.com/Expert-Visual-CLI-Programmers-Experts/dp/1590597567/ref=sr_1_1?ie=UTF8&s=books&qid=1242817008&sr=1-1 の Search inside this book で CHAPTER 10 Wrapping Native Libraries ・・・  Wapping C++ Classes    Mapping C++ Exeptions to Managed Exceptions とかあるのを見ると、「Nativeコードのデバッグを可能にするチェックをつけてデバッグ実行すると、」native側の例外をManaged側の例外として捕捉してくれるのかも(単なる想像ですが・・・)。

noridon
質問者

お礼

すみません、お礼を付け忘れてしまいました。 また何かありましたら、よろしくお願いします。

noridon
質問者

補足

ご回答有難うございます。 教えて頂いたURL見てきました。 デストラクタ内でのNativeの実体の削除は行なっていますが、例外が出ている所がnewですので、どうしたものかと。 それと、本のご紹介も有難うございました。 C++/CLIの本が出ているのですね、知りませんでした。 こちらを読み込めば、何かヒントが見つかるかもしれませんね。

  • chie65535
  • ベストアンサー率43% (8520/19368)
回答No.1

下手にラッパーを作ると、ラッパーの生成時に例外を吐くので、ラッパーを作ってはいけません。 以下のフォーラムを参考にして下さい。 http://vsug.jp/tabid/63/forumid/45/postid/2892/view/topic/Default.aspx

noridon
質問者

お礼

参考になりました。 有難うございました。

noridon
質問者

補足

ご回答有難うございます。 フォーラムの方も見てみたのですが、いまひとつ分りません。 unmanagedのC++ライブラリをDLLにして、P/Invokeで呼び出すという事でしょうか? ちなみに、C++/CLIでラップするという方法は、以下のサイトで知りました。 http://www.atmarkit.co.jp/fdotnet/special/vcppinvista01/vcppinvista01_03.html 現在、C++/CLIでラップするクラス群を作ってしまっていて、C#もその仕様に合わせて作り始めています。 出来れば、ラッパーを上手に作る方法を解説しているサイト等あれば、教えて頂ければ幸いです。

関連するQ&A

  • C++/CLIとC#の連携について

    いつも拝見させていただいております。 現在、C++/CLIとC#にて連携を行っているのですが、C++/CLIで作成したクラス配列 がC#側でどのようにすれば受け取れるのか方法がわかりません。 C++/CLIで作成しているクラス配列はSystem::Collections::Generic::Listを使用 して配列化しています。 下記がC++/CLIのソースになります。 List<testClass>^% testClass::GetList() { List<testClass>^ lpTestClassList = gcnew List<testClass>(); testClass^ lpTestClass; lpTestClass = gcnew testClass(); lpTestClassList->Add(lpWatchServiceMasterInfoWrapper); return lpTestClassList; } これをC#側で使用しようとすると下記エラーが発生します。  「この言語によってサポートされていません」 C++/CLI⇒C#間の連携ではListクラスを使用することは不可能なのでしょうか? クラスを配列にして引き渡したいだけなので、他の方法等含めて何か参考になることがありましたら ご教授ください。 よろしくお願い致します。 開発環境  C++/CLI ⇒ DLL(ネイティブなコードを参照するためのラッパー用DLL)  C# ⇒ アプリケーション

  • C#、C++間のDLLの呼び出しについて

    いつも拝見させていただいております。 さっそくですが、質問致します。 現在、ネイティブなC++ DLLを作成しています。 これを今回、C#のアプリケーションから呼び出すことになりました。 DLL内にはクラスを作成しており、内部にXMLのデータを保持するような クラスを作成しております。(XML操作にはMSXMLを使用しております。) 問題なのはC++アプリケーションから呼び出した時は正常に動作するのですが、C#からの呼び出しの時はC++アプリケーションから呼び出した時には発生していないエラーが検出されます。 エラー内容は System.AccessViolationException 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 になります。 エラー内容からしてC++内でのメモリ操作に問題があると 思われるのですが、C++からの実行時には検出されていないので理由がわからずに困っております。 ネイティブなDLLに対してはデバッグも行えないため、手に負えません。 (現在、1行ごとにログを埋め込み、TCHAR型のnewを4byte行っている箇所で処理がストップしてしまっているようです。C++からの呼び出し時には正常に処理される箇所です。) ネイティブなDLLに対してのデバッグ方法や似たような現象にあわれた方がいらっしゃいましたらご助力お願い致します。 ・対象のDLLのクラスは_declspec(dllexport)にてエクスポートを行っています。 ・C#からの呼び出し時にはネイティブなDLLのためC++/CLIで作成したプロジェクトでラッパークラスを作成してアクセスを行っています。 ・C++アプリケーションからの呼び出し時はプロパティの設定でインクルードディレクトリ、LIBファイルの設定等を行って直接DLLを参照して 実行(呼び出し)しています。

  • .NET C++/CLIのガーベジコレクションについて

    .NET C++/CLIのガーベジコレクションについて .NET C++/CLIで、マネージピープの配列をネイティブDLLにポインタ引数として渡す動作で、 配列が正常に渡っていることは確認したのですが、ネイティブDLL側で配列の処理をしている最中に、 ガーベジコレクションが起こり、誤動作することはあるのでしょうか。 ちなみに、マーシャリングは以下のように行いました。 // マネージ側コード [DllImport("native.dll")] void ArraySet( [MarshalAs(UnmanagedType::LPArray)] array <int> ^ Data ); array <int> ^ Data = gcnew array <int>(64); ArraySet( Data ); // この中で配列の処理中にガーベジコレクションが起こると誤動作?

  • MFCのC++/CLI へIntPtrをキャスト

    MFCのC++/CLI へIntPtrのデータを受け渡せません。。。 コードは以下になります。 ------------------------------ C# System.IntPtr hBitmap; p.GetBitmapHandle((void*)hBitmap);//CLI側のメソッド ------------------------------ C++/CLI (MFC) void GetBitmapHandle( void* hBitmap ){ hBitmap = m_hBitmap; } HBITMAP m_hBitmap; ------------------------------ 非常に困ってます。助けてください!

  • C#とC++/CLI間でポインタが指す内容が変わる

    現在、C++/CLIプログラムをC#で使う必要があり、 C++/CLIで定義したメソッドとクラスでC#側とやり取りする必要が生じております。 以下の書き方で、C++/CLIとC#間のクラスのやり取りはできたのですが、 C++/CLI側で定義されているメソッド内で、ポインタが指し示す値(*id.head)が変わってしまいます(文字化けみたいな感じになる)。 引き渡したポインタ変数の値は一致しているのですが、 どうすれば、C++/CLI側で値を正しく取得できるのでしょうか?。 【C++/CLI側で定義されているクラス】 public value class class1 { public : ULONG code; header    *head; }; typedef struct _header { CHAR achCHdrType[2]; CHAR achMsgLen[2]; } header ; 【C++/CLI側で定義されているメソッド】 ULONG session::open(class1& id) { return session_oepn(id.code, *id.head) } 【C#側でのメソッド参照】 class1 c1 = new class1(); uint status = session.open(&c1); よろしくお願いします。

  • C# 例外が発生しないことの保障

    Javaと比較して書きます。 Javaで記述した場合: public class JavaClass {  public static SampleClass s = new SampleClass(); } C#で記述した場合: public class CSharpClass {  public static SampleClass s = new SampleClass(); } JavaでもC#でも、同じコードを記述しているように見えますが、Javaではnew SampleClass()コンストラクタで例外が発生しない事が分かっているのに対して、C#の場合では例外が発生しないとは言い切れません。 これは、Javaでは、例外をスローする可能性のあるメソッド宣言では、その全てについてthrows宣言をしなければいけないのに対して、C#にはこの制約が存在しないことが原因です。 これについて何が困るかといいますと、C#で、static宣言な変数や静的コンストラクタで安易にメソッド呼び出し等を行うと、キャッチできなくなってしまいます。 public class Exceptionner {  public Exceptionner()  {   throw new ApplicationException("Exceptionnerクラスの例外");  } } public class SampleClass {  public static Exceptionner e = new Exceptionner(); // ここで例外が発生するが、キャッチできない。 } public class MyEntryPoint {  public static void Main()  {   try   {    SampleClass s = new SampleClass();   }   catch (Exception e)   {    // System.ApplicationExceptionでなくSystem.TypeInitializationExceptionとなる。    // つまり、元の例外の情報は失われている    Console.WriteLine(e.GetType());   }  } } これを現在漠然と問題視していますが、何かよい解決策はありませんでしょうか。 望んでいる解決策: ・C#でもメソッドが例外を返さないという保障がソースレベルでメソッドやコンストラクタに宣言可能? ・C#では例外をちゃんとキャッチしなくてもスマートに記述することが可能? ・問題視する必要がない?(whyも含めて)

  • C,C++,C++/CLIの構造体とクラス

    C++の構造体・クラスって、メンバのアクセス指定子のデフォルトが privateかpublicかという違い「だけ」しか全くないのでしょうか? クラスにおける value class / ref class という分類はC++/CLIのもので これについては value class の方は C言語の構造体に近いという事でいいでしょうか? ref classの方は ネイティブのC++のクラスを マネージ用にしたようなもので C++/CLIの構造体は C++のそれと同じで OKですか? そしてそれらの構造体には、値型・参照型といった分類はないのでしょうか?

  • [C++/CLI]可変個引数について

    visual studio 2005を使用し、C++で作ったクラスをVBで呼び出せるようにするため、C++でラッパクラスを作成中です。 ネイティブコードで可変個の引数を表すには、 Test(PSTR str, ...){ char ch[1024]; va_list ap; va_start(ap, str); wvsprintf( ch, str, ap ); va_end(ap);       ・       ・       ・ } のようにすればOKだったのですが、マネージコードで可変個の引数を使用するにはどうすれば良いのでしょうか。「ParamArray」というキーワードを使うのでしょうか? また、ラッパクラスではないクラスの可変個引数を使用しているメソッドで、 「warning C4793: 'vararg' : 関数 'DWORD CTest::Log(PSTR,...)' 用にネイティブ コードの生成が発生します」 というワーニングがでています。これは無視しても大丈夫なのでしょうか? 申し訳ございませんが、分かる方がいましたら回答をお願いします。

  • C++/CLIのリソースファイルについて

    C++/CLIのリソースファイルについて質問です。 環境は、Visual Studio 2005のC++/CLIです。 アセンブリリソースファイル(resx)の文字列リソースをEXEファイルをに含めることは可能でしょうか? 含めるか、含めないかの設定はどこで可能でしょうか? 現在は、EXEファイルと同じ場所にアセンブリリソースファイル(resx)がないと例外が発生します。

  • C++の投げる例外について

    VisualStdio2005でC++のプログラムを組んでいたところCtrl+F5で実行すると落ちてしまうバグを発見しました。 仕方ないのでF5で実行して場所を特定しようとしたのですがF5でデバッガを通すと動くのです。 そこでメッセージボックスでしらみつぶしに調べていった結果、ある特定の場所でnewしたところで落ちていることがわかりました。 しかしただのnewで、そのあとにしっかりとNULLチェックまでしているのですがNULLチェックに到達せずnewした瞬間落ちているようです。 デバッグウインドウには CTVTRegKeyOpenExceptionで例外が投げられましたと出ているのですがネットで検索しても1件しかヒットしません。 何か心あたりのある方はご教授願います。 WindowsXPPro メモリ2048MB CPU:Core2duo 2.33GHz VisualStdio2005

専門家に質問してみよう