Why do i get "Error: symbol is already defined" when instantiating a C++ template with function type
Why do i get "Error: symbol is already defined" when instantiating a C++ template with function type
我有一个包含 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
似乎 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;
}
我有一个包含 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
似乎 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;
}