考虑以下解决方案结构: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调用高级库。还有更好的办法吗?
答案 0 :(得分:1)
在桌面应用程序中,您可以使用AddDllDirectory
或SetDllDirectory
来修改搜索路径。但在Windows应用商店应用程序中,您无法使用这些功能。所以我看到两个选择:
LoadLibrary
将绝对路径传递给DLL以将其加载到进程中。在PInvokeServer1
之前加载PInvokeServer
。更改p / invoke声明以仅指定DLL文件名。也就是说,从p / invoke声明中删除Native
目录。通过显式调用LoadLibrary
,您可以确保将两个DLL加载到进程中。然后对p / invoke函数的后续调用将导致已经加载的DLL被使用。