2010-05-29 3 views
8

Gibt es eine Möglichkeit zu überprüfen, ob eine bestimmte Funktion mit C-Verknüpfung (also mit extern "C") zur Kompilierzeit deklariert ist?Überprüfen, ob eine Funktion C-Verknüpfung zur Kompilierungszeit hat [nicht auflösbar]

Ich entwickle ein Plugin-System. Jedes Plugin kann dem Plugin-Ladecode Factory-Funktionen zur Verfügung stellen. Dies muss jedoch über den Namen (und anschließende Verwendung von GetProcAddress oder dlsym) erfolgen. Dies erfordert, dass die Funktionen mit C-Verknüpfung deklariert werden, um eine Namensänderung zu verhindern. Es wäre schön, in der Lage zu sein, einen Compiler-Fehler zu werfen, wenn die referenzierte Funktion mit C++ - Verknüpfung deklariert wird (im Gegensatz zur Feststellung, dass zur Laufzeit eine Funktion mit diesem Namen nicht existiert).

Hier ist ein vereinfachtes Beispiel dafür, was ich meine:

extern "C" void my_func() 
{ 
} 

void my_other_func() 
{ 
} 

// Replace this struct with one that actually works 
template<typename T> 
struct is_c_linkage 
{ 
    static const bool value = true; 
}; 

template<typename T> 
void assertCLinkage(T *func) 
{ 
    static_assert(is_c_linkage<T>::value, "Supplied function does not have C-linkage"); 
} 

int main() 
{ 
    assertCLinkage(my_func); // Should compile 
    assertCLinkage(my_other_func); // Should NOT compile 
} 

Gibt es eine mögliche Implementierung von is_c_linkage, die einen Compiler-Fehler für die zweite Funktion werfen würden, aber nicht die erste? Ich bin mir nicht sicher, ob das möglich ist (obwohl es als Compiler-Erweiterung existieren könnte, von der ich immer noch gerne wissen würde). Vielen Dank.

+6

Ich vermute stark, dass dies nicht getan werden kann - vor allem nicht in einer Standard-Art und Weise. Interessante Frage. –

+2

Ich bin mir da nicht so sicher. Aber selbst wenn es möglich wäre, ist es sehr wahrscheinlich, dass GCC es nicht unterstützt, da es die Unterscheidung eines externen "C" - und eines externen "C++" - Funktionstyps nicht kennt. So behandelt es beide Arten gleich. –

+0

Wenn Sie zu implementationsspezifischem Wissen gehen, können Sie es auch für diese Implementierung verwenden, anstatt einen Fehler zu werfen. –

Antwort

2

Ich stimme Jonathan Leffler zu, dass dies wahrscheinlich nicht in einer Standard-Weise möglich ist. Vielleicht wäre es etwas möglich, abhängig vom Compiler und sogar der Version des Compilers, aber Sie müssten experimentieren, um mögliche Ansätze zu bestimmen und akzeptieren, dass das Verhalten des Compilers wahrscheinlich unbeabsichtigt war und in späteren Versionen "behoben" werden könnte.

Mit g++ Version 4.4.4 auf Debian Squeeze, zum Beispiel, können Sie möglicherweise einen Compiler-Fehler für Funktionen erhöhen, die nicht stdcall mit diesem Ansatz ist:

void my_func() __attribute__((stdcall)); 
void my_func() { } 

void my_other_func() { } 

template <typename ret_, typename... args_> 
struct stdcall_fun_t 
{ 
    typedef ret_ (*type)(args_...) __attribute__((stdcall)); 
}; 

int main() 
{ 
    stdcall_fun_t<void>::type pFn(&my_func), 
     pFn2(&my_other_func); 
} 

g++ -std=c++0x nicht diesen Code zu kompilieren, weil :

SO2936360.cpp:17: error: invalid conversion from ‘void ()()’ to ‘void ()()’

Zeile 17 ist die Deklaration pFn2. Wenn ich diese Deklaration loslasse, ist die Kompilierung erfolgreich.

Leider funktioniert diese Technik nicht mit cdecl.

0

Für Unix/Linux, wie wäre es mit der Analyse der resultierenden Binärdatei mit 'nm' und Suche nach Symbolnamen? Ich nehme an, es ist nicht das, was du meintest, aber trotzdem ist es eine Art Kompilierzeit.

Verwandte Themen