DllImport неполных имен - PullRequest
       10

DllImport неполных имен

1 голос
/ 14 сентября 2010

Я использую несколько P / Invokes под .NET.Однако я хочу, чтобы моя библиотека работала как в Windows, так и в Linux, предпочтительно с одними и теми же двоичными файлами.

Поскольку нативная библиотека, от которой я зависел, доступна на нескольких платформах, я надеялся, что они будут только вместе с моей управляемой библиотекой.Двоичные файлы библиотеки.

Сейчас я использую что-то вроде этого:

[DllImport("/usr/lib/libMYLIBNAME.so.1")]

Но это, очевидно, работает только для Linux.Я подумывал, что я мог бы скопировать этот двоичный файл из / usr / lib и распространять вместе с моим приложением, поэтому я мог бы уменьшить это до:

[DllImport("libMYLIBNAME.so")]

Но это все еще только для Linux.

Есть ли в любом случае изменить строку имени библиотеки, чтобы она искала libMYLIBNAME.so в Linux и MYLIBNAME.dll в Windows, или что-то очень похожее?

Я бы хотел избежать всего, что требует перекомпиляциидля каждой поддерживаемой платформы ...

(Примечание: еще лучше будет решение, которое будет искать MYLIBNAME.dll в Windows и /usr/lib/libMYLIBNAME.so.1 в Linux, но это улучшениепо желанию)

Ответы [ 3 ]

7 голосов
/ 14 сентября 2010

Две вещи

1 - DllImport без расширения Это поддерживается в Windows, Linux и MAC и будет импортировать соответствующую библиотеку для целевой платформы.

[DllImport("libMYLIBNAME")] - 

2- Предпочитаемыйможно использовать <dllmap/>, который позволяет сопоставить имя библиотеки импорта с именем библиотеки целевой платформы.Так что, если в Windows у вас есть dll с именем mylib.dll и соответствующий Linux, то есть mylinuxlib.so.3.6.1, вы можете импортировать ее, используя имя Windows DLL

[DllImport("mylib.dll")]

и добавить конфигурацию в конфигурацию для сопоставления этого именина имя библиотеки Linux

<configuration>
  <dllmap dll="mylib.dll" target="mylinuxlib.so.3.6.1" />
</configuration>

Подробнее Здесь

2 голосов
/ 14 сентября 2010

Windows не требовательна к расширению имени файла для DLL.Их изменение не является чем-то необычным, например, .ocx для элементов управления ActiveX, .scr для заставок.Но все равно обычная DLL.Загрузчик Windows проверяет подлинность файла по содержимому, заголовок PE32 делает его истинной DLL.

Так что просто переименуйте версию Windows .dll в .so.Измените настройку выходного имени компоновщика или просто переименуйте файл.

2 голосов
/ 14 сентября 2010

Одно из решений, которое я видел, - это создать абстрактный класс-оболочку для вашего P / Invokes и сгенерировать соответствующий класс на основе среды.

public abstract class Wrapper
{
   public void SomeMethod()
   {
      WrappedMethod();
   }

   public static Wrapper GetWrapper()
   {
      //TODO: write some method to determine OS
      return IsLinux() ? new LinuxWrapper() : new WindowsWrapper();
   }

   public abstract void WrappedMethod();
}

public class WindowsWrapper : Wrapper
{
  //windows dll imports go here

  public override void WrappedMethod()
  {
      //p/invokes go here
  }
}

public class LinuxWrapper : Wrapper
{
  //linux dll imports go here
  public override void WrappedMethod()
  {
     //p/invokes go here
  }
}
...