Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managed C++ with .NET Core 2.1

We have a library written in C++. To make it more compatible with our more modern .NET projects, we wrapped this C++ library in another .NET project. It works fine when referencing it from full .NET Framework projects (4.5, 4.6, etc.).

I am creating a new application using .NET Core 2.1 and I am trying to reference this "wrapped-in-.NET C++ library". On my first attempt, it failed saying the assembly couldn't be loaded. I fixed this problem by installing .NET Core SDK x86 and forcing my application to use x86, not Any CPU.

I get no build errors, but when I try to instantiate a class within this library, I get the following exception:

<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()

Does .NET Core 2.1 support this scenario at all?

like image 622
AndreFeijo Avatar asked Aug 21 '18 23:08

AndreFeijo


2 Answers

As others pointed out, .NET Core does not currently support C++/CLI (aka "managed C++"). If you want to call into native assemblies in .NET Core, you must use PInvoke (as you discovered).

You can also compile your .NET Core project in AnyCPU, as long as you keep around both 32- & 64-bit versions your native library and add special branching logic around your PInvoke calls:

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);
    }
}

Where you have your MyLibrary.amd64.dll and MyLibrary.x86.dll assemblies in the same directory. It would be nice if you could put relative paths into DllImport and have x86/amd64 subdirectories, but I haven't figured out how to do that.

like image 71
ahelwer Avatar answered Sep 28 '22 05:09

ahelwer


No it does not. .NET core is cross platform but C++/CLI is not, the Microsoft C++ compiler requires Windows.

like image 45
ADG Avatar answered Sep 28 '22 05:09

ADG