windows 应用调用两个具有相同名称的 C++ DLL 和链接到另一个 DLL 的 API
A windows app calls two C++ DLLs with same name and APIs linking to another DLL
我正在尝试让我的 C# 应用 运行 同时使用两个不同版本的 C++ DLL。
两个具有相同文件名和API的DLL位于不同的目录:
App -> V1/A.dll -> V1/B.dll
-> V2/A.dll -> V2/B.dll
来自 Dynamic-Link Library Search Order, I've learned how to make one A.dll call the B.dll in the same directory by LoadLibraryEx() and SetDllDirectory().
如果我的应用程序分别调用两个版本,它工作正常:
SetDllDirectory("V1");
v1 = LoadLibraryEx("V1/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
v1.open();
v1.runall();
v1.close();
SetDllDirectory("V2");
v2 = LoadLibraryEx("V2/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
v2.open();
v2.runall();
v2.close();
但是如果两个版本运行一帧一帧就出错了(被零除异常):
SetDllDirectory("V1");
v1 = LoadLibraryEx("V1/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
SetDllDirectory("V2");
v2 = LoadLibraryEx("V2/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
v1.open();
v2.open();
foreach (frame in frames)
{
v1.run(frame);
v2.run(frame); // divide-by-zero exception occurs
}
v1.close();
v2.close();
由于 v2 可能在 A.dll 或 B.dll 中调用了错误,我在 DLL 中添加了一些测试 API:
A.dll:
int _a = 0;
void set_var(int a, int b) {
_a = a;
set_var_b(b);
}
void get_var(int *a, int *b) {
*a = _a;
*b = get_var_b();
}
B.dll:
int _b = 0;
void set_var_b(int b) {
_b = b;
}
int get_var_b() {
return _b;
}
在B.dll中v1和v2似乎共享全局变量的相同数据内存,但在A.dll中却没有:
int a1, b1;
int a2, b2;
v1.get_var(&a1, &b1); // a1 = 0, b1 = 0
v2.get_var(&a2, &b2); // a2 = 0, b2 = 0
v1.set_var(1, 2);
v2.get_var(&a2, &b2); // a2 = 0, **b2 = 2**
v2.set_var(3, 4);
v1.get_var(&a1, &b2); // a1 = 1, **b1 = 4**
我的问题:
- 应用程序可以调用两个具有相同文件名的 DLL (A.dll) 和链接到另一个 DLL (B.dll) 的 API 吗?
- 如果对 1 的回答是肯定的,是否允许在 B.dll 中使用全局变量?如果不是,是什么原因?
感谢 Hans Passant 的评论。
在我之前的案例中,A.dll 的两个不同版本调用相同的 B.dll:
App -> V1/A.dll |-> V1/B.dll
-> V2/A.dll | V2/B.dll
清单可以解决这个问题:
- 为 A.dll 项目创建清单文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<file name="B.dll" />
</assembly>
- 将清单文件添加到 A.dll 项目的属性中:Manifest Tool -> Input and Output -> Additional Manifest Files
另请参阅:
我正在尝试让我的 C# 应用 运行 同时使用两个不同版本的 C++ DLL。
两个具有相同文件名和API的DLL位于不同的目录:
App -> V1/A.dll -> V1/B.dll
-> V2/A.dll -> V2/B.dll
来自 Dynamic-Link Library Search Order, I've learned how to make one A.dll call the B.dll in the same directory by LoadLibraryEx() and SetDllDirectory().
如果我的应用程序分别调用两个版本,它工作正常:
SetDllDirectory("V1");
v1 = LoadLibraryEx("V1/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
v1.open();
v1.runall();
v1.close();
SetDllDirectory("V2");
v2 = LoadLibraryEx("V2/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
v2.open();
v2.runall();
v2.close();
但是如果两个版本运行一帧一帧就出错了(被零除异常):
SetDllDirectory("V1");
v1 = LoadLibraryEx("V1/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
SetDllDirectory("V2");
v2 = LoadLibraryEx("V2/A.dll", null, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
SetDllDirectory(null);
v1.open();
v2.open();
foreach (frame in frames)
{
v1.run(frame);
v2.run(frame); // divide-by-zero exception occurs
}
v1.close();
v2.close();
由于 v2 可能在 A.dll 或 B.dll 中调用了错误,我在 DLL 中添加了一些测试 API:
A.dll:
int _a = 0;
void set_var(int a, int b) {
_a = a;
set_var_b(b);
}
void get_var(int *a, int *b) {
*a = _a;
*b = get_var_b();
}
B.dll:
int _b = 0;
void set_var_b(int b) {
_b = b;
}
int get_var_b() {
return _b;
}
在B.dll中v1和v2似乎共享全局变量的相同数据内存,但在A.dll中却没有:
int a1, b1;
int a2, b2;
v1.get_var(&a1, &b1); // a1 = 0, b1 = 0
v2.get_var(&a2, &b2); // a2 = 0, b2 = 0
v1.set_var(1, 2);
v2.get_var(&a2, &b2); // a2 = 0, **b2 = 2**
v2.set_var(3, 4);
v1.get_var(&a1, &b2); // a1 = 1, **b1 = 4**
我的问题:
- 应用程序可以调用两个具有相同文件名的 DLL (A.dll) 和链接到另一个 DLL (B.dll) 的 API 吗?
- 如果对 1 的回答是肯定的,是否允许在 B.dll 中使用全局变量?如果不是,是什么原因?
感谢 Hans Passant 的评论。
在我之前的案例中,A.dll 的两个不同版本调用相同的 B.dll:
App -> V1/A.dll |-> V1/B.dll
-> V2/A.dll | V2/B.dll
清单可以解决这个问题:
- 为 A.dll 项目创建清单文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <file name="B.dll" /> </assembly>
- 将清单文件添加到 A.dll 项目的属性中:Manifest Tool -> Input and Output -> Additional Manifest Files