你如何从c ++调用托管(c#)函数?

时间:2009-09-24 06:11:23

标签: c# c++ managed-c++

我有一个c#dll项目(my_cs_dll.dll),它定义了一个带有静态成员函数的静态类。

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 ++项目的Common Properties references部分添加了对'my_cs_dll.dll'的引用(复制本地/复制依赖项都是True)。

我还在c ++项目中添加了'my_cs_dll.dll'的路径配置属性C / C ++一般'使用引用解析#'部分。

所有内容都是在没有错误的情况下构建的,但是在运行时我不断从系统中获取“System.IO.FileNotFound”异常,声称它无法找到my_cs_dll.dll程序集。

两个Dll都存在于我正在运行的同一目录中。

我在上面提到的设置上尝试了各种各样的变化,并阅读了我在manged / unmanaged interop上可以找到的所有内容,但我似乎无法让我的大脑绕过什么错误......

我正在使用VS2008&amp; .NET 3.5

1 个答案:

答案 0 :(得分:4)

听起来你的C#程序集在运行时没有被解析。您的C#dll与可执行文件的(或子目录)位于同一目录中吗?我做了这个已经有一段时间了,但我的回忆是,除非你的程序集安装在GAC中,它必须位于你的可执行文件所在的目录(或子目录)中,而不是使用的dll的位置它。这与.NET安全功能有关。

如果您仍然遇到问题,可以尝试自行解决装配问题。在启用clr的C ++项目中,尝试添加以下内容:

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的项目中创建了一个类的两个函数静态方法。只需确保在代码的早期就调用Resolve()功能,即在尝试拨打get_number_from_cs()之前。

虽然使用COM是一种选择,但没有必要。用你当前的方法走在正确的道路上。如果你想要一些手持,请看看这个CodeProject example。这是我为了让我的非托管应用程序使用我的托管程序集而遵循的。