Можно ли объявить и использовать указатель на функцию без сигнатуры?
От: Klirik  
Дата: 23.11.13 10:07
Оценка:
Задача такая. Есть исходный код с примерно такой конструкцией:

...
#inlcude "mysql.h"
...
mysql_init ( &m_tMysqlDriver );
...



Захотелось отвязаться от явной связи с библиотекой и сделать динамическую загрузку. Для этого сделаны следующие изменения:


...
#include "mysql.h"
...
#if DL_MYSQL

typedef MYSQL *        STDCALL (*xmysql_init)(MYSQL *mysql);
... // тут ещё 14 подобных typedef для других нужных функций
...
class CMysql...
{
...
public:
    bool Init()... // грузит библиотеку; кладёт адреса нужных функций в члены-статики.
    static xmysql_init m_pmysql_init;
...
};

#define sph_mysql_init (*CMysql::m_pmysql_init)
...

xmysql_init CMysql::m_pmysql_init = NULL;
...

CMysql MysqlHoder;

bool InitDynamicMysql()
{
    return MysqlHoder.Init();
}

#else // !DL_MYSQL

#define sph_mysql_init mysql_init
#define InitDynamicMysql() (true)

#endif // DL_MYSQL

...
if (!InitDynamicMysql())
  ... // что-то пошло не так, ругаемся и вылетаем;
 
sph_mysql_init ( &m_tMysqlDriver );
...


В общем — ничего волшебного; обычная рутинная загрузка. Макрос DL_MYSQL определяется configure-скриптом, и позволяет задействовать старый статический вариант без накладных расходов.
Но вот с динамическим вариантом... да, всё работает. Но смущает вот это:

...
typedef MYSQL *        STDCALL (*xmysql_init)(MYSQL *mysql);
...


В смысле — я залез в файл mysql.h и вытащил оттуда прототип mysql_init. Окружил имя (*x...) и получил указатель на функцию (а потом так же 14 раз для остальных использованных функций).
Выглядит коряво, нелогично и избыточно!
Возник вопрос — а нельзя ли как-нибудь объявить указатель на функцию, не цитируя явно её сигнатуру?
Т.е. у нас есть "чёрный ящик" — хедер, где объявлена функция.
Мы знаем имя нужной функции и хотим объявить указатель, в который можно положить адрес на эту функцию, и потом разыменовывать и использовать его как исходную функцию, НЕ цитируя явно её прототип из хедера.
Возможно ли такое?

Как один из вариантов смотрел на такой "велосипед":

#if DL_MYSQL
#define mysql_init (*xmysql_init)
... // другие подобные строки для других нужных функций
#include "mysql.h"
...



Получится, что нужный указатель будет объявлен прямо из хедера, за счёт подстановки стоящего перед ним #define. Но! Это уже не typedef а прямое объявление переменной. В рамках одного исходника работает, но если вынести в хедер и включить несколько раз — получаются множественные объявления.
Также не думал о возможных краевых эффектах (например, что будет, если функция используется в самом хедере, в inline-определении другой функции?).

Что подскажете, господа програмисты? Неужели такой "велосипед" — это единственный способ забороть ситуацию?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.