#c #templates #dll #shared-libraries
#c #шаблоны #dll #совместно используемые библиотеки #общие библиотеки
Вопрос:
У меня есть простая библиотека DLL с 4 функциями, 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 foundn");
}
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. Пожалуйста, опубликуйте свои команды компиляции / ссылки для mingw
2. Искаженное имя, на которое он жалуется, таково: void CallFunction<int (*)(int, int)>(HINSTANCE_ , char const )
Ответ №1:
Кажется, что 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;
}
Комментарии:
1. о, вау, это сложный обходной путь… это ошибка в GCC или просто недостаток его дизайна?
2. @Youda008 ну, вы могли бы создавать
StdCall
иCdecl
не шаблоны и просто кодироватьint(int,int)
непосредственно как их типы, но это довольно жестко. Что касается того, является ли это ошибкой, я думаю, что это так, но я не уверен, находится ли это на уровне mingw или на уровне gcc.