我在.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,但这种改进是可选的)
答案 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即可。更改链接器的输出名称设置或只重命名文件。