4

C# をスクリプト言語として C++ ライブラリに埋め込もうとしています。これは簡単な作業ではない可能性があることを認識していたので、最初にこれが可能かどうかを確認するために最小限のテスト プロジェクトを作成しました。

簡単なスクリプトを管理し、実行時にCSharpCodeProvider. アセンブリは、C# コンソール アプリをテスト プロジェクトとして使用してテストされました (C# ソース ファイルがメモリ内でコンパイルされ、必要に応じて実行される場合)。

次のステップは、これを C++ アプリケーションで橋渡しすることでした。

私は何とかCOMを使用してそれを行うことができました。C# dll、クラス、およびインターフェイスを COM オブジェクトとしてエクスポートし、Regasm を使用して tlb ファイルを生成しました。

C++ プロジェクトでこれらのクラスのインスタンスを作成し、それらのメソッドを呼び出すことができWindows.Forms、実際のロジックを実行する必要があるまで、すべて正常に動作しているように見えました (メッセージ ボックスの表示など)。ライブラリのホストとして C# コンソール アプリで既に動作しているため、スローしてはならない例外をスローするだけです。

COM コンポーネントをデバッグできるかどうかわからないので (この C# dll のコードに足を踏み入れることはできません)、大量のメッセージ ボックスと try-catch ブロックを追加しました。

コンパイルされたアセンブリから任意の型を取得しようとすると、壊れているようです。それはスローします:Reflection.ReflectionTypeLoadException

一方、コンパイルは失敗せず、エラー メッセージも生成されません。

C# を使用してこれらのメソッドをトリガーすると 100% 機能しますが、C++ から実行している間だけ何らかの理由で機能しなくなります。

これの原因は何ですか?または、私がやろうとしていることを別の方法で行うことができますか? このようなシナリオで COM を使用するのはどういうわけか正しいと思いますが、そのようなコードが壊れる原因となることに気付いていない側面がありますか?

編集: これは、COM としてエクスポートされたマネージ C# アセンブリです: http://nopaste.info/9da70dbcbd.html

したがって、これらのオブジェクトは次のように C++ アプリからアクセスされます: http://nopaste.info/50c4c9726a.html

また、スクリプトは、メッセージ ボックスを表示するメソッドから派生しIScriptて実装するクラスと同じくらい単純です。Execute

編集2:

スローされた例外に関する詳細は次のとおりです。

最後の文は、ファイルが見つからなかったことを意味します。

しかし、コンパイル時に次の行があるため、これは奇妙です。

これは「スクリプト」の内容です。

using System;
using System.Linq;
using System.Windows.Forms;
using System.Reflection;
using lame2.scripting;

namespace Olaboga
{
  public class TestScript : IScript
  {
    public TestScript() { }

    public void Execute(Event ev)
    {
      MessageBox.Show("Script that has been compiled from a source file has been invoked.   TestScript.Execute");
    }
  }
}

編集3:

最後に、メモリ内でのコンパイルから一時ファイルへのコンパイルに切り替えた後、突然正常に動作し始めました。したがって、最後の質問は、メモリ内でコンパイルされているときに機能しなかった理由と、それが可能かどうかを誰かが知っている可能性があります。

4

1 に答える 1

4

アプリケーションの機能を COM オブジェクト モデルとして公開できる場合は、それが可能になるはずです。.NET 相互運用層で適切に処理できる方法でインターフェイスをモデル化するように注意する必要があります。

私の理解が正しければ、C# スクリプトから生成された .NET アセンブリのデバッグに問題があるのではないでしょうか? この場合、アセンブリのコンパイル時に次のコンパイラ設定を使用できます。

CompilerParameters cp = new CompilerParameters();

// Generate debug information.
cp.IncludeDebugInformation = true;

// Save the assembly as a physical file.
cp.GenerateInMemory = false;

// Set a temporary files collection. 
// The TempFileCollection stores the temporary files 
// generated during a build in the current directory, 
// and does not delete them after compilation.
cp.TempFiles = new TempFileCollection(".", true);

これにより、ソース コード、デバッグ シンボル、およびアセンブリと同様に、生成されたコードのデバッグが可能になります。ただし、「COMコンポーネント」について数回言及しましたが、何も表示されません-C++アプリと.NETアセンブリがあります-その間のものは実際のCOMコンポーネントではなく、多かれ少なかれ「相互運用魔法」です、これら 2 つの当事者間で物をマーシャリングするだけです。

実装を含む元の .NET アセンブリのデバッグに問題がある場合は、デバッグ設定が正しいことを確認してください。

  • ネイティブアプリで正常にデバッグを開始する場合(F5)、に移動してProject Settings -> Debugging -> Debugger Typeに設定しますMixed
  • デバッガーを実行中のプロセスにアタッチする場合は、Attach to ProcessフォームSelect...で「アタッチ先」テキストボックスの近くのボタンをクリックし、必要なもの (マネージドおよびネイティブ) を選択します。

これは、アセンブリのソース コードと .pdb ファイルがあることを前提としています。

于 2012-10-01T11:30:54.660 に答える