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

mar*_*ark 5 c# c++ managed-c++

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

namespace Foo
{
    public static class Bar
    {
        public static double GetNumber() { return 1.0; }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还有一个使用/ clr的c ++ dll项目.

#using <my_cs_dll.dll>

double get_number_from_cs() { return Foo::Bar::GetNumber(); }
Run Code Online (Sandbox Code Playgroud)

'my_cs_dll.dll'在c ++项目的Common Properties references部分添加了一个引用(复制本地/复制依赖项都是True).

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

一切都没有错误地构建,但是在运行时我不断从系统获得"System.IO.FileNotFound"异常,声称它无法找到my_cs_dll.dll程序集.

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

我已经在上面提到的设置上尝试了各种各样的变化,并阅读了我在manged/unmanaged interop上可以找到的所有内容,但我似乎无法弄清楚我的大脑有什么问题...

我正在使用VS2008和.NET 3.5

Mat*_*vis 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;
}
Run Code Online (Sandbox Code Playgroud)

您可能需要稍微调整代码才能使其在您的项目中编译。就我而言,我在启用 clr 的项目中将两个函数设置为类的静态方法。只需确保Resolve()在代码中尽早调用该函数,即在尝试调用get_number_from_cs().

虽然使用 COM 是一种选择,但不是必需的。按照您当前的方法,您走在正确的道路上。如果您需要一些指导,请查看此CodeProject 示例。这是我为了让我的非托管应用程序使用我的托管程序集而遵循的一个。