Не допускать удаления экспортируемой функции компоновщиком

У меня есть программа, котораястатически ссылки с несколькими библиотеками c ++, которые экспортируют несколько функций:

extern "C" 
{ 
    KSrvRequestHandler* CreateRequestHandler( const char* name );
    bool                DestroyRequestHandler( KSrvRequestHandler* handler );
    const char**        ListRequestHandlerTypes();
}

Затем основная программа вызывает эти функции, используя GetProcAddress / dlsym:

#ifdef WIN32

   HINSTANCE hDll = GetModuleHandle( NULL );

   mCreateHandler   = GetProcAddress( hDll, createFuncName  );
   mDestroyHandler  = GetProcAddress( hDll, destroyFuncName );
   mGetHandlerTypes = GetProcAddress( hDll, listFuncName    );

#else // POSIX

   void* handle = dlopen( NULL, 0 );

   mCreateHandler   = dlsym( handle, createFuncName  ); 
   mDestroyHandler  = dlsym( handle, destroyFuncName ); 
   mGetHandlerTypes = dlsym( handle, listFuncName    ); 
   dlclose( handle );

#endif // !POSIX

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

(Почему я делаю это выходит за рамки вопроса, но короткий ответ: это архитектура плагинов, но у меня есть несколько стандартных плагинов, которые связаны непосредственно с основным двоичным файлом - но я все еще хочу загрузить их через ту же загрузку плагинов интерфейс. Например, для встроенных плагинов я загружаю их, передавая текущий исполняемый файл в качестве источника интерфейсов плагинов.)

Вот проблема: компоновщик не знает, что мне понадобятся эти функции, и не связывает их.

Как заставить эти функции быть связаны между собой? Для динамической библиотеки их экспорта достаточно. Но для exe, даже экспортированная dll функция удаляется компоновщиком.

Я знаю, что, вероятно, смогу принудительно установить связь, заставив основной двоичный файл назначить эти адреса функций чему-либо или какому-нибудь другому подобному хаку Есть ли правильный способ сделать это?

@ ОБНОВЛЕНИЕ: Итак, у меня есть решение, которое работает, но оно внутри безобразно. Все еще ищу лучший путь.

Поэтому мне нужно как-то определить нужные мне символы в объекте, который загружает встроенные интерфейсы. Я не думаю, что есть способ заставить компоновщик ссылаться на символ иначе. Например. Я не знаю, как создать библиотеку с функцией, которая всегда связана, независимо от того, нужна она или нет. Это полностью на усмотрение шага ссылки для исполняемого файла.

Поэтому в исполняемом файле у меня есть макрос, который определяет необходимые мне встроенные интерфейсы. Каждый встроенный плагин имеет префикс для всех своих функций интерфейса, поэтому в верхней части файла я делаю:

DEFINE_BUILT_IN_PLUGIN( PluginOne )
DEFINE_BUILT_IN_PLUGIN( PluginTwo )

Это заставит определения функций мне нужно. Но макрос для этого настолько уродлив, что я переполнен чувствами ярости и неуверенности в себе (для удобства чтения я удалил косые черты из макроса):

#define FORCE_UNDEFINED_SYMBOL(x) 
    void* _fp_ ## x ## _fp =(void*)&x; 
    if (((ptrv) _fp_ ## x ##_fp * ( rand() | 1 )) < 1 ) 
        exit(0);

#define DEFINE_BUILT_IN_PLUGIN( PREFIX )  

extern "C" 
{                                                                                                   
    KSrvRequestHandler* PREFIX ## CreateRequestHandler( const char* name );
    bool                PREFIX ## DestroyRequestHandler( KSrvRequestHandler* handler );      
    const char**        PREFIX ## ListRequestHandlerTypes();
}  

class PREFIX ## HandlerInterfaceMagic
{      
public:
    PREFIX ## HandlerInterfaceMagic()
    {
        FORCE_UNDEFINED_SYMBOL( PREFIX ## CreateRequestHandler );
        FORCE_UNDEFINED_SYMBOL( PREFIX ## DestroyRequestHandler );
        FORCE_UNDEFINED_SYMBOL( PREFIX ## ListRequestHandlerTypes ); 
    }
};               
PREFIX ## HandlerInterfaceMagic PREFIX ## HandlerInterfaceMagicInstance;

Поскольку компилятор является оптимизирующим родом, в FORCE_UNDEFINED_SYMBOLS я собираюсь изо всех сил обмануть компилятор и связать функцию, на которую нет ссылок. Этот макрос работает только внутри функции. Поэтому я должен создать этот фальшивый класс Magic. Должен быть лучший способ.

Во всяком случае - это работает.

Ответы на вопрос(3)

Ваш ответ на вопрос