У нас есть библиотека, написанная на C ++. Чтобы сделать его более совместимым с нашими более современными проектами .NET, мы поместили эту библиотеку C ++ в другой проект .NET. Он отлично работает при обращении к нему из проектов .NET Standard (4.5, 4.6 и т. Д.).
Я создаю новое приложение, используя .NET Core 2.1, и я пытаюсь сослаться на эту «обернутую- .NET C ++ библиотеку». С моей первой попытки не удалось сказать, что сборка не может быть загружена. Я исправил эту проблему, установив .NET Core SDK x86 и заставив мое приложение использовать 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 этот сценарий вообще?
Как отмечали другие, .NET Core в настоящее время не поддерживает C ++ / CLI (он же «управляемый C ++»). Если вы хотите вызывать нативные сборки в .NET Core, вы должны использовать PInvoke (как вы обнаружили).
Вы также можете скомпилировать свой .NET Core проект в AnyCPU, если вы будете использовать оба & 64-битные версии вашей нативной библиотеки и добавление специальной логики ветвления вокруг ваших вызовов PInvoke:
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, но я не понял, как это сделать.
Нет. Ядро .NET является кроссплатформенным, а C ++ / CLI — нет, компилятору Microsoft C ++ требуется Windows.
PInvoke кажется, единственный путь.
Поместите библиотеку DLL в папку решения (действительная библиотека C ++, а не оболочка .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.