使用.NET Core 2.1进行托管C++

12

我们有一个用C++编写的库。为了使它与我们更现代的.NET项目更兼容,我们在另一个.NET项目中包装了这个C++库。当从完整的.NET Framework项目(4.5、4.6等)引用它时,它运行良好。

我正在使用.NET Core 2.1创建一个新应用程序,并尝试引用这个“包裹在.NET C++库中”的库。在第一次尝试时,它失败并显示程序集无法加载。我通过安装.NET Core SDK x86并强制我的应用程序使用x86而不是Any CPU来解决了这个问题。

我没有构建错误,但当我尝试实例化此库中的类时,我会得到以下异常:

<CrtImplementationDetails>.ModuleLoadException: The C++ module failed to load.
 ---> System.EntryPointNotFoundException: A library name must be specified in a DllImport attribute applied to non-IJW methods.
   at _getFiberPtrId()
   at <CrtImplementationDetails>.LanguageSupport._Initialize(LanguageSupport* )
   at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* )
   --- End of inner exception stack trace ---
   at <CrtImplementationDetails>.ThrowModuleLoadException(String errorMessage, Exception innerException)
   at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* )
   at .cctor()

.NET Core 2.1是否支持这种情况?


包装器项目的.NET版本是什么? - ahelwer
嗨@ahelwer,这是.NET 4.0。 - AndreFeijo
顺便说一下,我们也尝试使用.NET 4.6,但返回了相同的错误。 - AndreFeijo
请明确一下 - 这个包装器项目是一个使用PInvoke调用本地库的.NET项目,还是一个C++/CLI项目(也称为“托管C ++”)? - ahelwer
C++/CLI(又称“托管 C++”)。 - AndreFeijo
1
没错,正如其他人所回答的那样,.NET Core不支持C++/CLI,尽管您已经发现PInvoke可以正常工作。 - ahelwer
3个回答

10
正如其他人指出的那样,.NET Core目前不支持C++/CLI(也称“托管C++”)。如果要在.NET Core中调用本机程序集,必须使用PInvoke(正如你所发现的那样)。
你还可以将.NET Core项目编译为AnyCPU,只要保留32位和64位版本的本机库,并在PInvoke调用周围添加特殊分支逻辑。
using System;

public static class NativeMethods
{
    public static Boolean ValidateAdminUser(String username, String password)
    {
        if (Environment.Is64BitProcess)
        {
            return NativeMethods64.ValidateAdminUser(username, password);
        }
        else
        {
            return NativeMethods32.ValidateAdminUser(username, password);
        }
    }

    private static class NativeMethods64
    {
        [DllImport("MyLibrary.amd64.dll", EntryPoint = "ValidateAdminUser", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern Boolean ValidateAdminUser(String username, String password);
    }

    private static class NativeMethods32
    {
        [DllImport("MyLibrary.x86.dll", EntryPoint = "ValidateAdminUser", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern Boolean ValidateAdminUser(String username, String password);
    }
}

当你在同一个目录下拥有MyLibrary.amd64.dll和MyLibrary.x86.dll程序集时。如果你能够将相对路径放入DllImport中,并且有x86/amd64子目录,那就太好了,但我还没有弄清楚如何做到这一点。


6

不,它不支持。.NET Core是跨平台的,但C++/CLI不是,Microsoft C++编译器需要Windows。


1
更多信息请参见Will CoreCLR支持C++/CLI跨平台? - omajid

2

PInvoke 似乎是唯一的解决方法。

将库的 DLL 放置在解决方案文件夹中(实际的 C++ DLL,而不是 .NET 封装器)。

注意:不要在解决方案中引用 DLL,只需将 DLL 放置在同一文件夹中。

然后使用DLL 导入 来访问方法:

static class NativeMethods
{
    [DllImport("MyLibrary.dll", EntryPoint = "ValidateAdminUser", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern Boolean ValidateAdminUser(String username, String password);
}

注意 2:仍需要将.NET Core项目运行在x86架构中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接