DllImport不完整的名字

时间:2010-09-14 16:57:45

标签: c# .net pinvoke portability dllimport

我在.NET下使用了几个P / Invokes。但是,我希望我的库可以在Windows和Linux中工作,最好使用相同的二进制文件。

由于我所依赖的本机库可以在多个平台上使用,所以我希望将它们与托管库的二进制文件一起使用。

现在我正在使用这样的东西:

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

但这显然只适用于Linux。我正在考虑我可以从/ usr / lib复制那个二进制文件并随我的应用程序一起分发,所以我可以将上面的内容减少到:

[DllImport("libMYLIBNAME.so")]

但这仍然只是Linux。

无论如何都要更改库名称字符串,以便在Linux下查找libMYLIBNAME.so,在Windows上查找MYLIBNAME.dll,或者是非常类似的东西?

我想避免任何需要为每个支持的平台重新编译的内容......

(注意:更好的解决方案是在Windows上寻找MYLIBNAME.dll,在Linux上寻找/usr/lib/libMYLIBNAME.so.1,但这种改进是可选的)

3 个答案:

答案 0 :(得分:7)

两件事

1- DllImport没有扩展名 这在Windows,Linux和MAC上受支持,并将为目标平台导入适当的库。

[DllImport("libMYLIBNAME")] - 

2-优先选项是使用<dllmap/>,它允许您将导入库名称映射到目标平台库名称。因此,如果在Windows上你有一个名为mylib.dll的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>

了解更多Here

答案 1 :(得分:2)

我见过的一个解决方案是围绕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
  }
}

答案 2 :(得分:2)

Windows对于DLL的文件扩展名并不挑剔。更改它们并不罕见,例如,ActiveX控件的.ocx,屏幕保护程序的.scr。但仍然是一个普通的DLL。 Windows加载程序从内容中验证文件的标识,PE32标头使其成为真正的DLL。

所以只需将.dll的Window版本重命名为.so即可。更改链接器的输出名称设置或只重命名文件。