c # — реализовать механизм, подобный [DllImport]

Вот моя проблема: в библиотеке PCL я собираюсь вызывать неуправляемый код из C ++ DLL. Эта DLL поставляется в двух версиях (x86 и x64), и из соображений производительности следует указывать правильную библиотеку в зависимости от платформы, в которую встроена библиотека PCL.

Так как [DllImport] Атрибут требует постоянной строки в качестве имени библиотеки, этот очень удобный способ делает его бесполезным, так как правильная библиотека должна быть определена во время выполнения. Есть несколько «мужественных» способов загрузить функции вручную (LoadLibrary, GetProcaddress а также GetDelegateForFunctionPointer) но я собираюсь сделать это более удобным для программиста.

Таким образом, объявление внешней функции не является проблемой. Что ж, компилятор C # обнаруживает внешнее и беспокоится о том, что при отсутствии [DllImport] атрибут, внешний может не быть разрешен при загрузке типа. Хорошо, я определил атрибут [MyImport] и поместил его во внешнем объявлении и бинго, по крайней мере, компилятор был счастлив.

Во время выполнения я, конечно, получаю исключение TypeLoadException, потому что мое внешнее действительно не разрешено. Это поднимает два вопроса:

1) Почему компилятор доволен каким-либо атрибутом?
Есть ли какая-либо магия в загрузчике в отношении использования этого атрибута для разрешения ожидающего внешнего? Это может быть легко сделано путем предоставления интерфейса, который будет реализован атрибутом. Таким образом, среда выполнения будет искать атрибуты внешнего поиска для тех, которые реализуют «магический» интерфейс.

2) Как я могу поймать исключение TypeLoadException таким образом, чтобы я мог реализовать свой собственный загрузчик?
Этот загрузчик будет перебирать все внешние объекты данного типа, считывать атрибут [MyImport] и разрешать внешние таким образом.

Есть ли какая-либо идея, если одна из двух идей может быть реализована или есть какое-либо другое решение упомянутой проблемы?

Я ценю уроки английского, но на самом деле это не то, о чем я прошу :-))

Кристиан.

4

Решение

На самом деле я пошел с решением, упомянутым Гансом, далее в разделе комментариев.

Как он упомянул, вся проблема — это скорее проблема развертывания, а не то, что нужно решать с помощью обходного пути. Итак, я дал двум версиям платформы одно и то же имя и позволил им находиться в разных каталогах — вот так:

SystemTera.MyPCL.dll
x86\SystemTera.Platform.dll
x64\SystemTera.Platform.dll

После запуска я указываю загрузчику правильную версию платформы:

public static class Platform
{
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string pathName) ;

public static void Setup()
{
if (Environment.Is64BitProcess)
SetDllDirectory("./x64/") ;
else // default Win32
SetDllDirectory("./x86/") ;
}
}

Когда я далее обращаюсь к библиотекам платформы, загрузчик / джиттер делает правильную работу:

public class MyClass
{
[DllImport("SystemTera.Platform.dll")]
static extern void MyPlatformFunction() ;

public void DoTheJob()
{
MyPlatformFunction() ;
}
}

Это прекрасное решение с использованием существующих концепций, предоставляемых платформой.

1

Другие решения


По вопросам рекламы [email protected]