web-dev-qa-db-ja.com

.NET Core 2.1を使用したManaged C ++

C++で記述されたライブラリがあります。最新の.NETプロジェクトとの互換性を高めるために、このC++ライブラリを別の.NETプロジェクトでラップしました。完全な.NET Frameworkプロジェクト(4.5、4.6など)から参照する場合は正常に機能します。

.NET Core 2.1を使用して新しいアプリケーションを作成していますが、この「ラップされた.NET C++ライブラリ」を参照しようとしています。私の最初の試みで、アセンブリをロードできなかったと言って失敗しました。 .NET Core SDK x86をインストールし、アプリケーションにAny CPではなくx86を使用するように強制することで、この問題を修正しました。

ビルドエラーは発生しませんが、このライブラリ内でクラスをインスタンス化しようとすると、次の例外が発生します。

<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はこのシナリオをまったくサポートしていますか?

7
AndreFeijo

他の人が指摘したように、.NET Core 現在C++/CLIをサポートしていません (別名「マネージC++」)。 .NET Coreのネイティブアセンブリを呼び出す場合は、 PInvoke (発見したとおり)を使用する必要があります。

32ビットと64ビットの両方のバージョンをネイティブライブラリに保持し、PInvoke呼び出しに特別な分岐ロジックを追加する限り、AnyCPUで.NET Coreプロジェクトをコンパイルすることもできます。

using System;

public static class NativeMethods
{
    public static Boolean ValidateAdminUser(String username, String password)
    {
        if (Environment.Is64BitProcess)
        {
            return NativeMethods64.ValidateAdminUser(String username, String password);
        }
        else
        {
            return NativeMethods32.ValidateAdminUser(String username, String 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サブディレクトリを作成できればいいのですが、その方法はわかりません。

7
ahelwer

いいえ、違います。 .NETコアはクロスプラットフォームですが、C++/CLIはそうではありません。MicrosoftC++コンパイラにはWindowsが必要です。

5
ADG

PInvokeが唯一の方法であるようです。

ライブラリDLL=ソリューションフォルダー(.NETラッパーではなく、実際のC++ DLL)に置きます。

注:ソリューション内でDLLを参照せず、同じフォルダにDLLを配置するだけです。

次に、DLL Importを使用してメソッドにアクセスします。

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

注2:それでも、x86アーキテクチャで実行するには.NET Coreプロジェクトが必要です。

1
AndreFeijo