为什么在实例化具有函数类型的C ++模板时会出现“错误:已定义符号”

时间:2016-10-19 10:34:54

标签: c++ templates dll shared-libraries

我有一个包含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

1 个答案:

答案 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;
}