Проверка, имеет ли функция C-связь, во время компиляции [неразрешимую]

Есть ли любой способ проверить, объявляется ли заданная функция с C-связью (то есть, с extern "C") во время компиляции?

Я разрабатываю сменную систему. Каждый плагин может предоставить функции фабрики к загружающему плагин коду. Однако это должно быть сделано через имя (и последующее использование GetProcAddress или dlsym). Это требует, чтобы функции были объявлены с C-связью, чтобы предотвратить искажение имени. Было бы хорошо смочь бросить ошибку компилятора, если упомянутый, которым функция объявляется с C ++-linkage (в противоположность обнаружению во времени выполнения, когда функция с тем именем не существует).

Вот упрощенный пример того, что я имею в виду:

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
}

Есть ли возможная реализация is_c_linkage это бросило бы ошибку компилятора для второй функции, но не первое? Я не уверен, что это возможно (хотя это может существовать как расширение компилятора, которое я все еще хотел бы знать).Спасибо.

8
задан scjohnno 31 May 2010 в 20:46
поделиться

2 ответа

Я согласен с Джонатаном Леффлером, что это, вероятно, невозможно стандартным способом. Возможно, это было бы возможно в некоторой степени, в зависимости от компилятора и даже версии компилятора, но вам придется экспериментировать, чтобы определить возможные подходы и принять тот факт, что поведение компилятора, вероятно, было непреднамеренным и может быть "исправлено" в более поздних версиях.

Например, в g++ версии 4.4.4 на Debian Squeeze, вы могли бы поднять ошибку компилятора для функций, которые не являются stdcall с помощью такого подхода:

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 не компилирует этот код, потому что:

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

Строка 17 - это объявление pFn2. Если я избавлюсь от этого объявления, то компиляция пройдет успешно.

К сожалению, эта техника не работает с cdecl.

2
ответ дан 6 December 2019 в 01:39
поделиться

Для Unix/Linux, как насчет анализа полученного двоичного файла с помощью 'nm' и поиска имен символов? Полагаю, это не то, что вы имели в виду, но все же это своего рода время компиляции.

0
ответ дан 6 December 2019 в 01:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: