我有一个包含4个函数的简单DLL库,其中2个使用__stdcall和2个默认的__cdecl调用约定。
在我的可执行文件中,我想调用所有这4个函数,我正在使用它的模板。代码如下:
#include <windows.h>
#include <stdio.h>
template<typename FuncType>
void CallFunction( HMODULE hModule, const char * name )
{
FuncType function = (FuncType)GetProcAddress( hModule, name );
if (function)
printf("result: %d.\n", function(1,2) );
else
printf("%s not found (%lu)\n", name, GetLastError());
}
typedef int (* FuncType1)(int, int);
typedef int (__stdcall * FuncType2)(int, int);
int main(int argc, char** argv)
{
HMODULE hModule = LoadLibrary( TEXT("library.dll") );
if (hModule) {
CallFunction<FuncType1>( hModule, "File1_Funkce1" );
CallFunction<FuncType2>( hModule, "File1_Funkce2" );
CallFunction<FuncType1>( hModule, "File2_Funkce1" );
CallFunction<FuncType2>( hModule, "File2_Funkce2" );
FreeLibrary( hModule );
}
else {
printf("library not found\n");
}
return 0;
}
这可以很好地编译Visual Studio编译器,但是使用MinGW会抛出错误:
Error: symbol '__Z12CallFunctionIPFiiiEEvP11HINSTANCE__PKc' is already defined
。我不明白为什么以这种方式使用模板会导致多个定义,因为您可以在同一个翻译单元中多次正常实例化vector<int>
和vector<char>
,并且不会发生错误。
有什么想法吗?
修改 我的编译命令很简单:
cl file.cpp
g++ file.cpp -o file.exe
答案 0 :(得分:2)
当修改模板名称并导致名称冲突时,似乎mingw忽略__stdcall
。您可以通过在自己的类型中编码这些指针来避免这种情况:
template<typename Func>
struct StdCall;
template<typename R, typename... Params>
struct StdCall<R(Params...)>
{
using type = R(__stdcall *)(Params...);
};
template<typename Func>
struct Cdecl;
template<typename R, typename... Params>
struct Cdecl<R(Params...)>
{
using type = R(*)(Params...);
};
然后你会打电话给他们:
CallFunction<StdCall<int(int,int)>>();
CallFunction<Cdecl<int(int,int)>>();
您必须更改CallFunction
才能调用::type
,但是:
template<typename FuncType>
void CallFunction( )
{
using Func = typename FuncType::type;
}