解析WinRT包中的本机库

时间:2014-05-26 10:39:26

标签: c# dll windows-8 pinvoke loadlibrary

考虑以下解决方案结构:Windows Store C#application + 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,并且我收到Module not found异常。例如,将PInvokeServer1.dll放置到System32目录没有帮助。

案例2:PInvoke能够直接加载PInvokeServer1.dll。

案例3.加载PInvokeServer1.dll后,也可以成功加载PInvokeServer.dll。

我的真实程序我有原生C库,取决于其他几个库。所有这些库都添加到C#Store应用程序包中。但是无法加载高级库,因为PInvoke无法加载依赖项。我能想到的唯一方法是使用LoadLibrary PInvoke调用加载低级库,最后使用PInvoke调用高级库。还有更好的办法吗?

1 个答案:

答案 0 :(得分:1)

在桌面应用程序中,您可以使用AddDllDirectorySetDllDirectory来修改搜索路径。但在Windows应用商店应用程序中,您无法使用这些功能。所以我看到两个选择:

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