解析WinRT包内的本地库
本文关键字:WinRT 包内 解析 | 更新日期: 2023-09-27 18:05:23
考虑以下解决方案结构:Windows Store c#应用程序+ 2个本地库PInvokeServer和PInvokeServer1。本地库代码:
// PInvokeServer1
PINVOKESERVER1_API int TestFunction1(void)
{
return 5;
}
// PInvokeServer
PINVOKESERVER_API int TestFunction(void)
{
return TestFunction1();
}
两个函数都是extern C
。PInvokeServer依赖于PInvokeServer1(使用链接依赖)。PInvokeServer.dll和PInvokeServer1.dll是通过构建动作内容添加到c#项目中的,所以它们是应用程序包的一部分。c#声明:
const string dllName = @"Native'PInvokeServer.dll";
const string dllName1 = @"Native'PInvokeServer1.dll";
[System.Runtime.InteropServices.DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern int TestFunction();
[System.Runtime.InteropServices.DllImport(dllName1, CallingConvention = CallingConvention.Cdecl)]
public static extern int TestFunction1();
情况1,不工作(未找到模块):
TestFunction();
案例2,作品:
TestFunction1();
案例3,作品:
TestFunction1();
TestFunction();
案例1:当PInvoke试图加载PInvokeServer.dll时,它无法解决本机运行时依赖,PInvokeServer1.dll未加载,并且我得到模块未发现异常。例如,将PInvokeServer1.dll放在System32目录下没有帮助。
案例2:PInvoke能够直接加载PInvokeServer1.dll
3。一旦PInvokeServer1.dll被加载,PInvokeServer.dll也可以被成功加载。
在我的实际程序中,我有依赖于其他几个库的本地C库。所有这些库都被添加到c# Store应用程序包中。但是无法加载高级库,因为PInvoke无法加载依赖项。我能想到的唯一方法是使用LoadLibrary
PInvoke调用加载低级库,最后使用PInvoke调用高级库。有没有更好的办法?
在桌面应用程序中,您可以使用AddDllDirectory
或SetDllDirectory
修改搜索路径。但是在Windows Store应用程序中,这些功能是不可用的。所以我看到两个选项:
- 将两个dll放在与可执行文件相同的目录中。从某种程度上说,这是最简单、最安全的解决方案。可执行文件的目录总是搜索的第一个位置,所以你可以确保正确的dll将被加载。
- 在调用DLL中的任何函数之前,调用
LoadLibrary
将绝对路径传递给DLL以将它们加载到进程中。在PInvokeServer
之前加载PInvokeServer1
。更改您的p/invoke声明以仅指定DLL文件名。也就是说,从p/invoke声明中删除Native
目录。通过显式调用LoadLibrary
,您可以确保将这两个dll加载到进程中。然后对p/invoke函数的后续调用将导致已经加载的dll被使用。