C# 解析WinRT包内的本机库

C# 解析WinRT包内的本机库,c#,dll,windows-8,pinvoke,loadlibrary,C#,Dll,Windows 8,Pinvoke,Loadlibrary,考虑以下解决方案结构:Windows应用商店C#应用程序+2个本机库PInvokeServer和PInvokeServer 1。本机库代码: // PInvokeServer1 PINVOKESERVER1_API int TestFunction1(void) { return 5; } // PInvokeServer PINVOKESERVER_API int TestFunction(void) { return TestFunction1(); } 这两个函数都是e

考虑以下解决方案结构:Windows应用商店C#应用程序+2个本机库PInvokeServer和PInvokeServer 1。本机库代码:

// PInvokeServer1
PINVOKESERVER1_API int TestFunction1(void)
{
    return 5;
}

// PInvokeServer
PINVOKESERVER_API int TestFunction(void)
{
    return TestFunction1();
}
这两个函数都是
extern C
。PInvokeServer依赖于PInvokeServer 1(使用链接器依赖项)。PInvokeServer.dll和PInvokeServer 1.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,不工作(未找到模块):

案例2,工程:

    TestFunction1();
案例3,工程:

    TestFunction1();
    TestFunction();
案例1:当PInvoke尝试加载PInvokeServer.dll时,它无法解析本机运行时依赖项,PInvokeServer 1.dll未加载,并且我得到模块未找到异常。例如,将PInvokeServer1.dll放在System32目录中没有帮助

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

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


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

在桌面应用程序中,您可以使用
AddDllDirectory
SetDllDirectory
修改搜索路径。但在Windows应用商店应用程序中,这些功能对您不可用。因此,我看到两种选择:

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

  • 谢谢,将本机库放到C#项目目录解决了这个问题。使用
    LoadLibrary
    进行显式加载也可以,但是当库与可执行文件位于同一目录中时,就不需要这样做了。
        TestFunction1();
        TestFunction();