我有几个dll文件,a.dll和b.dll都有一个输出函数test。
a.dll的源码
======================================================================================
a.cpp
#include <windows.h>
namespace a
{
int WINAPI test(void)
{
return 0;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
a.def
LIBRARY a
EXPORTS
test
======================================================================================b.dll的源码
======================================================================================
b.cpp
#include <windows.h>
namespace b
{
int WINAPI test(void)
{
return 1;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
b.def
LIBRARY b
EXPORTS
test
======================================================================================我现在想做一个c.dll,也包含test输出函数,在奇数时调用a.dll中的test,偶数时调用b.dll中的test。
于是我将a.lib,b.lib复制到c的目录下。
c.dll的源码如下:
======================================================================================
c.cpp
#include <windows.h>
#pragma comment(lib, "a.lib")
#pragma comment(lib, "b.lib") namespace a
{
int WINAPI test(void);
}
namespace b
{
int WINAPI test(void);
}
namespace c
{
int WINAPI test(void)
{
static int i;
i++;
if(i%2)
{
return a::test();
}
else
{
return b::test();
}
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
c.def
LIBRARY c
EXPORTS
test
======================================================================================c.dll程序可以通过编译,却无法链接。请问高手,这样的程序该如何链接。
我不要LoadLibrary动态加载,动态加载dll我也会。只要静态编译链接,如何实现?
a.dll的源码
======================================================================================
a.cpp
#include <windows.h>
namespace a
{
int WINAPI test(void)
{
return 0;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
a.def
LIBRARY a
EXPORTS
test
======================================================================================b.dll的源码
======================================================================================
b.cpp
#include <windows.h>
namespace b
{
int WINAPI test(void)
{
return 1;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
b.def
LIBRARY b
EXPORTS
test
======================================================================================我现在想做一个c.dll,也包含test输出函数,在奇数时调用a.dll中的test,偶数时调用b.dll中的test。
于是我将a.lib,b.lib复制到c的目录下。
c.dll的源码如下:
======================================================================================
c.cpp
#include <windows.h>
#pragma comment(lib, "a.lib")
#pragma comment(lib, "b.lib") namespace a
{
int WINAPI test(void);
}
namespace b
{
int WINAPI test(void);
}
namespace c
{
int WINAPI test(void)
{
static int i;
i++;
if(i%2)
{
return a::test();
}
else
{
return b::test();
}
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
c.def
LIBRARY c
EXPORTS
test
======================================================================================c.dll程序可以通过编译,却无法链接。请问高手,这样的程序该如何链接。
我不要LoadLibrary动态加载,动态加载dll我也会。只要静态编译链接,如何实现?
个人觉得,虽然命名空间允许你定义同名函数,但是你这种情况显然应该用接口实现,然后通过“动态载入”而不是“静态载入”方式调用。使用“命名空间”和“def”文件这种混合方式是否能真的有解决方法,我很怀疑。即使有解决方法,也不是平凡解法(也就是不是大众所熟知的解法),这在软件工程中要努力避免的。
同样,在你的各个namespcae之间,你没有办法区分链接的是哪个函数,所以你无法调用正确的函数你可以尝试将他们封装在类中,但与你的要求不符要是你非要重名,那就要动态加载,建议你将dll中函数改名。
namespace a
{
int WINAPI test(void);
}
namespace b
{
int WINAPI test(void);
}
因为你这里只声明了函数,没有定义函数体。根据你的意思是要分别调用 dll a b中的test函数,但是implicit link貌似没有办法解决名字冲突.
方法1:取消def中的test输出,用__declspec(dllexport)
c.dll的源码:
======================================================================================
c.cpp
#include <windows.h>
#pragma comment(lib, "a.lib")
#pragma comment(lib, "b.lib") extern "C" {
__declspec(dllexport) int test(void);
}namespace a
{
int WINAPI test(void);
}
namespace b
{
int WINAPI test(void);
} int test(void)
{
static int i;
i++;
if(i%2)
{
return a::test();
}
else
{
return b::test();
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
c.def
LIBRARY c
EXPORTS
====================================================================================== 方法二:将test改名,然后在def中重命名
c.dll的源码:
======================================================================================
c.cpp
#include <windows.h>
#pragma comment(lib, "a.lib")
#pragma comment(lib, "b.lib") namespace a
{
int WINAPI test(void);
}
namespace b
{
int WINAPI test(void);
} int mytest(void)
{
static int i;
i++;
if(i%2)
{
return a::test();
}
else
{
return b::test();
}
}
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
--------------------------------------------------------------------------------------
c.def
LIBRARY c
EXPORTS
test = mytest
======================================================================================
int WINAPI mytest(void)
令一个用LoaLibrary动态载入
尽管如此,我还是不赞同你使用其中任何一种方法。方法1是对namespace的滥用,我个人更倾向于防止不同的函数提供者直接的命名冲突,你自己不应该故意创造冲突,至于方法2:这违背了c++对重载支持的初衷。
个人还是喜欢使用定义公共接口,然后dll中分别实现的方法
extern "C" {
__declspec(dllexport) int test(void);
}
生成的标示符是_test
int WINAPI mytest(void)
生成的标示符是?mytest@@YGHXZ我推测def定义沿用的是c的标准,不知道区分?test@a@@YGHXZ、?test@b@@YGHXZ和?test@c@@YGHXZ,统一识别为test
改了标识符后,链接器就能确切的知道该导出的是哪个函数了。