解析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调用高级库。有没有更好的办法?

解析WinRT包内的本地库

在桌面应用程序中,您可以使用AddDllDirectorySetDllDirectory修改搜索路径。但是在Windows Store应用程序中,这些功能是不可用的。所以我看到两个选项:

  1. 将两个dll放在与可执行文件相同的目录中。从某种程度上说,这是最简单、最安全的解决方案。可执行文件的目录总是搜索的第一个位置,所以你可以确保正确的dll将被加载。
  2. 在调用DLL中的任何函数之前,调用LoadLibrary将绝对路径传递给DLL以将它们加载到进程中。在PInvokeServer之前加载PInvokeServer1。更改您的p/invoke声明以仅指定DLL文件名。也就是说,从p/invoke声明中删除Native目录。通过显式调用LoadLibrary,您可以确保将这两个dll加载到进程中。然后对p/invoke函数的后续调用将导致已经加载的dll被使用。