Как загрузить функцию с помощью dlsym () без reinterpret_cast? - PullRequest
5 голосов
/ 26 марта 2019

Я пытаюсь использовать clang-tidy для обеспечения соблюдения основных принципов C ++.Хотя у него много правильных точек, есть одна вещь, которую я не могу обойти: dlsym возвращает void*, который мне нужно как-то превратить в правильный указатель на функцию.Для этого я использую reinterpret_cast.Поскольку руководящие принципы запрещают это, у меня есть предупреждения об этом.Конечно, я могу разместить //NOLINT комментариев везде, но я ищу решение, которое не использует reinterpret_cast, поэтому предупреждения исчезают.

Есть ли обходные пути для этой проблемы?

1 Ответ

6 голосов
/ 26 марта 2019

В языке нет другого способа привести тип указателя функции к типу указателя объекта, кроме reinterpret_cast. Это определяется поведением, определенным реализацией [expr.reinterpret.cast] / 8 :

Преобразование указателя функции в тип указателя объекта или наоборот поддерживается условно. Смысл такого преобразования определяется реализацией, за исключением того, что если реализация поддерживает преобразования в обоих направлениях, преобразование prvalue одного типа в другой тип и обратно, возможно, с другой квалификацией cv, должно давать исходное значение указателя.

Это означает, что соответствующий компилятор C ++ должен документ, если он не поддерживает эту функцию. И, если он это поддерживает, он должен задокументировать, как именно он себя ведет. Вы можете положиться на то, что он работает (или не доступен) задокументированным способом на этом компиляторе.

Относительно основных руководящих принципов: Если вам нужно поставить //NOLINT "везде", то это может означать, что вы называете голым dlsym() во многих местах. Попробуйте обернуть его, например

template <typename T>
inline T* lookupSymbol(void* module, const char* name)
{
    auto symbol = reinterpret_cast<T*>(dlsym(module, name));  // NOLINT

    if (!symbol)
        throw std::runtime_error("failed to find symbol '"s + name + '\'');

    return symbol;
}
...