Zachowaj eksportowaną funkcję przed usunięciem przez linker

Mam taki programstatycznie linki z kilkoma bibliotekami c ++, które eksportują kilka funkcji:

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

Następnie program główny wywołuje te funkcje za pomocą 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

Kluczem jest tutaj wywołanie funkcji w moim własnym programie głównym za pomocą dynamicznego łączenia.

(Dlaczego to robię jest poza zakresem pytania, ale krótka odpowiedź: jest to architektura wtyczek, ale mam kilka standardowych wtyczek, które są połączone bezpośrednio z głównym plikiem binarnym - ale nadal chcę je załadować za pomocą tego samego wtyczki ładującej np. dla wbudowanych wtyczek ładuję je, przekazując bieżący plik wykonywalny jako źródło interfejsów wtyczek.)

Oto problem: linker nie wie, że będę potrzebował tych funkcji i nie łączy ich.

Jak wymusić połączenie tych funkcji? W przypadku dynamicznej biblioteki wystarczy ich eksport. Ale w przypadku exe nawet funkcja eksportu do biblioteki DLL jest usuwana przez linker.

Wiem, że prawdopodobnie mogę wymusić powiązanie, sprawiając, że główny plik binarny przypisze te adresy funkcji do czegoś lub innego podobnego hacka. Czy jest odpowiedni sposób, aby to zrobić?

@UPDATE: Mam więc rozwiązanie, które działa - ale z pewnością jest brzydkie w środku. Wciąż szukam lepszego sposobu.

Muszę w jakiś sposób zdefiniować symbole, których potrzebuję w obiekcie, który ładuje wbudowane interfejsy. Nie sądzę, aby istniał sposób zmuszenia linkera do powiązania symbolu w inny sposób. Na przykład. Nie wiem, jak zbudować bibliotekę z funkcją, która zawsze jest powiązana z wyglądem, czy nie. Jest to całkowicie zależne od kroku łącza dla pliku wykonywalnego.

W pliku wykonywalnym mam makro, które definiuje wbudowane interfejsy, których potrzebuję. Każda wbudowana wtyczka ma prefiks do wszystkich funkcji interfejsu, więc na górze pliku robię:

DEFINE_BUILT_IN_PLUGIN( PluginOne )
DEFINE_BUILT_IN_PLUGIN( PluginTwo )

Spowoduje to wymuszenie definicji funkcji, których potrzebuję. Ale makro, aby to zrobić, jest tak brzydkie, że jestem pełen uczuć wściekłości i wątpliwości (usunąłem końcowe ukośniki z makra dla czytelności):

#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;

Ponieważ kompilator jest genuis optymalizującym, w FORCE_UNDEFINED_SYMBOLS staram się oszukać kompilator do połączenia funkcji bez referencji. To makro działa tylko wewnątrz funkcji. Muszę więc stworzyć tę fałszywą Magiczną klasę. Musi być lepszy sposób.

W każdym razie - to działa.

questionAnswers(3)

yourAnswerToTheQuestion