2009-09-24 7 views
5

私は静的メンバー関数を持つ静的クラスを定義するC#dllプロジェクト(my_cs_dll.dll)を持っています。C++からどのようにマネージド(c#)関数を呼び出すのですか?

namespace Foo 
{ 
    public static class Bar 
    { 
     public static double GetNumber() { return 1.0; } 
    } 
} 

また、/ clrを使用しているC++ dllプロジェクトもあります。

#using <my_cs_dll.dll> 

double get_number_from_cs() { return Foo::Bar::GetNumber(); } 

私はC言語で'my_cs_dll.dll'への参照を追加しました++プロジェクトの共通のプロパティは、(ローカル/コピーの依存関係がともに真でコピー)のセクションを参照しています。

また、私は、C++プロジェクトの構成プロパティC/C++の一般的な「解決する#参照を使用して」セクションに'my_cs_dll.dll'へのパスを追加しました。

すべてがエラーなしでビルドされますが、実行時にはmy_cs_dll.dllアセンブリが見つからないと主張するシステムから 'System.IO.FileNotFound'例外が引き続き発生します。

両方のDllは、私が実行しているのと同じディレクトリに存在します。

私は...

を上記の設定のバリエーションのすべての種類を試してみましたが、私はうまく管理/管理対象外の相互運用に見つけることができるすべてのものを読んで、私は何が間違っているの周りに私の脳を得るように見えることはできませんしています'm using VS2008 & .NET 3.5

答えて

4

実行時にC#アセンブリが解決されないようです。あなたのC#dllはあなたの実行ファイルと同じディレクトリ(またはそのサブディレクトリ)にありますか?私がこれをしてからしばらく時間がかかりましたが、あなたのアセンブリがGACにインストールされていないと、使用しているDLLの場所ではなく、実行可能ファイルがあるディレクトリ(またはサブディレクトリ)になければなりませんそれ。これは.NETのセキュリティ機能と関係があります。

問題が解決しない場合は、アセンブリを自分で解決してみてください。

using namespace System; 
using namespace System.Reflection; 
void Resolve() 
{ 
    AppDomain::CurrentDomain->AssemblyResolve += 
     gcnew ResolveEventHandler(OnAssemblyResolve); 
} 
Assembly ^OnAssemblyResolve(Object ^obj, ResolveEventArgs ^args) 
{ 
#ifdef _DEBUG 
    String ^path = gcnew String(_T("<path to your debug directory>")); 
#else 
    String ^path = gcnew String(_T("<path to your release directory>")); 
#endif 
    array<String^>^ assemblies = 
     System::IO::Directory::GetFiles(path, _T("*.dll")); 
    for (long ii = 0; ii < assemblies->Length; ii++) { 
     AssemblyName ^name = AssemblyName::GetAssemblyName(assemblies[ii]); 
     if (AssemblyName::ReferenceMatchesDefinition(gcnew AssemblyName(args->Name), name)) { 
      return Assembly::Load(name); 
     } 
    } 
    return nullptr; 
} 

あなたはそれがあなたのプロジェクトでコンパイルするために取得するためのコードを少し微調整する必要があります:あなたのCLR対応のC++プロジェクトでは、以下を追加してみてください。私の場合、私はclr対応プロジェクトでクラスの静的メソッドを2つの関数にしました。 Resolve()関数をコードの早い段階、つまりget_number_from_cs()に呼び出す前に呼び出すようにしてください。

COMを使用することはオプションですが、必要ありません。あなたは現在のアプローチで正しい道を歩んでいます。あなたが手に持ちたい場合は、CodeProject exampleを見てください。アンマネージドアプリケーションで管理対象アセンブリを使用するためには、これが私が従うものです。 のdllのは、exeファイルの下にいくつかのサブディレクトリをネストされている「それを使っているDLLの場所とは対照的に、あなたの実行ファイルが、配置されて、それはディレクトリ(またはサブディレクトリ)でなければなりません」

+0

こんにちはマット、 。マネージdllを実行可能ファイルと同じディレクトリに移動すると、問題が解決しました。 ありがとうございました! – mark

+0

OK、よろしくお願いします。私は、DLLが実行可能ファイルのサブディレクトリにある限り、どれほど深いかに関係なく、アセンブリは解決されるという印象を受けました。しかし、私が言ったように、私はこれを見てからしばらくしています。 –

+0

埋め込みリソースからC#DLLを読み込むときに同様のコードを使用しました。そのトリックは、C#DLLを参照していないファイルにこのコードを配置することでした。それは遅延ロードのようだ。ネットアセンブリは、問題のアセンブリへの参照を含むコンパイル単位(.cppファイル)へのエントリ時に発生します。 – mheyman

関連する問題