2013-04-15 3 views
10

Очевидно, что отличное отключение между указателями функций и указателями объектов является неопределенным поведением в общем смысле, но POSIX (см.: dlsym) и WinAPI (см.: GetProcAddress) требуют этого.GCC предупреждает о функции Указатель на указатель на объект Cast

Учитывая это, и учитывая тот факт, что такой код нацелен на API, специфичный для платформы, в любом случае его переносимость на платформы, где указатели на объекты и указатели объектов несовместимы, на самом деле неактуальны.

Но -Wpedantic предупреждает об этом в любом случае, и #pragma GCC diagnostic ignored "-Wpedantic" не имеет никакого эффекта:

warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default] 

Я хочу, чтобы держать -Wpedantic включен, так как он дает хорошие предупреждения, но я не хочу иметь реальные предупреждения и ошибки, потерянные в море нерелевантных предупреждений о указателе на указатели объектов на указатели объектов.

Есть ли способ сделать это?

Запуск GCC 4.8.0 на Windows, (MinGW):

gcc (rubenvb-4.8.0) 4.8.0 

КОД ОБРАЗЦА

#include <windows.h> 
#include <iostream> 


int main (void) { 

    std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),"five")) << std::endl; 

} 

Издает (с -Wpedantic):

warning_demo.cpp: In function 'int main()': 
warning_demo.cpp:7:87: warning: ISO C++ forbids casting between pointer-to-funct 
ion and pointer-to-object [enabled by default] 
    std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"), 
"five")) << std::endl; 

    ^
+0

У меня никогда не было проблемы с выдачей результата «GetProcAddress». – chris

+2

У вас есть * код *, который сгенерировал это предупреждение, которое вы можете отправить? – WhozCraig

+0

@WhozCraig Добавлено в вопрос. –

ответ

3

Я думаю, вы могли бы использовать г ++ s system_header директиву здесь:

wrap_GetProcAddress.h:

#ifndef wrap_GetProcAddress_included 
#define wrap_GetProcAddress_included 

#pragma GCC system_header 

template <typename Result> 
Result GetProcAddressAs([normal parameters]) 
{ 
    return reinterpret_cast<Result>(GetProcAddressAs([normal parameters])); 
} 

#endif 
+0

'#pragma GCC system_header'. Спасибо, что поставил меня на правильный путь. –

2

Там в всегда трюк memcpy, который вы можете использовать:

int (*f)() = 0; 
int *o; 
memcpy(&o, &f, sizeof(int*)); 

Вы можете увидеть его на ideone: m is generating warnings, while g is OK.

Что касается других действий, которые вы могли бы предпринять: одной очевидной возможностью было бы «исправить» заголовок, определяющий dlsym, чтобы фактически вернуть указатель функции (например, void (*)()). Удачи с этим.

+0

Вы должны хотя бы static_assert, чтобы указатель функции был достаточно большим, чтобы удерживать 'void *'. –

+0

Ну, проблема с 'GetProcAddress' тогда становится тем, что если вы хотите получить адрес того, что не является функцией в загруженной вами библиотеке (см. Пример кода, который я добавил к вопросу)? –

+1

@MarkB: Учитывая, что OP хочет использовать POSIX, который фактически [требует, чтобы указатели функций имели такое же представление, что и указатели объектов) (http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html # tag_15_12), я считаю это лишним беспорядком (аналогично обработке 'sizeof (char)', отличной от 1). Но если вы чувствуете, что вам это нужно, вы можете добавить его (в этом случае я бы скорее поставил его в сценарий autoconf или somesuch). – jpalecek

3

Это прекрасно работает.

template <typename RESULT, typename ...ARGS> 
void * make_void_ptr(RESULT (*p)(ARGS...)) { 
    static_assert(sizeof(void *) == sizeof(void (*)(void)), 
        "object pointer and function pointer sizes must equal"); 
    void *q = &p; 
    return *static_cast<void **>(q); 
} 
Смежные вопросы