我有一个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++项目的“公共(public)属性”引用部分中添加了对'my_cs_dll.dll'的引用(拷贝本地/拷贝依赖关系均为True)。
而且,我还在C++项目的“配置属性”“C/C++常规'使用引用的引用'”部分添加了'my_cs_dll.dll'的路径。
一切都构建正确,但是在运行时,我不断从系统获取“System.IO.FileNotFound”异常,声称它找不到my_cs_dll.dll程序集。
这两个DLL文件肯定都存在于我正在运行的同一目录中。
我已经尝试了上述设置的各种变体,并阅读了在有人操作/非托管互操作中可以找到的所有内容,但是我似乎无法弄清问题所在……。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我正在使用Visual Studio 2008和.NET 3.5。

最佳答案

听起来您的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。这是我要让我的非托管应用程序使用托管程序集的程序。

关于c# - 如何从C++调用托管(C#)函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1470009/

10-11 23:14
查看更多