что указатель на таблицу виртуальных функций расположен по смещению 0 (а дальше идут поля)?
Если нельзя, есть ли более-менее надёжный кроссплатформенный способ прочитать vtable для объекта?
Кроссплатформенный способ для некроссплатформенного vtable? Даже учитывая, что оно везде
0) Нельзя утверждать, что класс не участвует в множественном наследовании. Это всегда можно сделать. 1) Нет, указатель на таблицу виртуальных функций вообще не доступен приложению в явном виде. 2) Нет, способа нет.
И даже больше, на сколько я знаю: С точки зрения стандарта vtable не существует
Я делаю FFI, у приложения будет свой ламповый интерфейс. Позвольте, чтобы исключить проблему XY описать задачу: мне нужно вернуть указатель на нечто. Этот указатель на нечто другой (недоступный мне) кусок программы интерпретирует как Base* и потом вызывает коллбэки: onStart, onEvent и т.д. Я формирую объект Wrapper в куче, для Wrapper - я отключаю выравнивание, - первым полем у меня идёт указатель на массив функций. - дальше данные Возвращаю указатель на этот Wrapper. Я так понимаю это не совсем надёжно, можно ли надёжнее?
если ваш код и недоступный вам кусок программы компилируются разными компиляторами (разными версиями одного компилятора), то стандарт не дает вам никаких гарантий, что внутренняя структура объектов Base будет одинаковой если хочется надежно, то надо сишное апи (и, соответственно, ABI) и с++ обертка над ним
А почему бы не вернуть указатель на произвольного наследника Base?
Составлять руками vtable в С, чтобы в дальнейшем пользоваться ею как "настоящей" из С++? Тут грабли на каждом шагу, даже в случае конкретной реализации
Я не в C++, я можно сказать в C (на самом деле в Rust, но не суть).
Понятно, то есть правильный способ: сделать прослойку на C++ с набором extern C функций.
Если что, есть расточатик
Кто мне подскажет лучше лейаут C++ объектов, если не эксперты по языку. В расточатике обычно с лайфтаймами воюют :-P
дык нет стандарта на лейаут
Но есть standard layout :)
Можно, не отключай выравнивание, не делай pack, не отсвечивай указатель на таблицу виртуальных функций. Не делай никаких предположений о размещении членов класса (и функций) в памяти, делай это всё в явном виде.
Сшное апи тут не поможет и не помешает... Оно тут ни при чём.
у него объекты будут ходить между библиотекой и клиентским кодом. ABI ни при чем, конечно
Не отключать выравнивание? 32/64 бита не выстрелят в ногу в этом случае? А ещё что значит "не отсвечивай указатель на таблицу"?
но удовлетворяет ли ему Base
Зачем тебе адреса членов, (смещения) , адрес( смещение) указателя на таблицу виртуальных методов?
Если мы говорим о виртуальности, то нет. Но сишное апи как раз гарантирует
Что там оно тебе гарантирует?
Чтобы сформировать в точности объект, который вызывающий код на С++ будет использовать прозрачно, как будто это нативный наследник Base. Но вообще по обсуждению выше я уже понял, что это плохая затея, лучше смаппить все методы Base в портянку extern C функций Base_onStart, Base_onEvent и так далее. Тогда мне неважно, по какому смещению vtable, но к сожалению это требует копипасты и возни с параметрами, плюс подтягивания C++ компилятора для моего кода. Но вроде должно получиться...
Standard layout, конечно
но вы же на стороне клиента потом обернете эти функции в нормальный класс, который изначально хотели?
Да, конечно, нужно предоставить удобный апи.
Вообще, не обязательно даже по адресу vtable будет находиться начало vtable
Я вот эту статью читал, https://shaharmike.com/cpp/vtable-part1/ Там правда автор только clang использует, поэтому его выводы ограничены.
Ну тут бы стоило читать конкретный ABI: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable
Пожалуй. Но я пошёл другим путём уже 😊 зы, спасибо за ссылку
Еще могу добавить что порядок функций в vtable может отличаться в разных компиляторах. Если я ничего не напутал я видел такое не совпадение между msvc и mingw. Опять же, если мне не изменяет память был флажок для mingw заставляющий использовать порядок принятый на винде, но это еще одна причина не закладываться на vtable.
Любопытное наблюдение. В принципе, если было бы только два варианта размещения, то я бы согласился на #ifdef :-) Но товарищи выше подсказывали, что может быть много...
Ну если это msvc, то там abi полиморфных интерфейсов стабилен, на этом весь COM держится, думаю в других компиляторах так же
очень похоже на правду, но мне недостает квалификации и опыта быстро расписать, как готовить плюсовое ABI и какие там грабли, хотя бы основные, поэтому предложил технически более простое решение, каким оно мне видится если вы так можете, я сам с удовольствием почитаю
Вопрос чуток в сторону. Оптимезирую вот такую конструкцию unordert_map< string_view, function<void() >> . 1) если хорошие альтернативы 2) может по женить с корутинами?
А что оптимизируешь, это же структура данных...
а ты осознанно выбрал string_view для использования в качестве ключа в unordered_map? это же прямой путь в загробный мир.
А вдруг там определенные в compile time литералы?
Тогда const char* очевидно
а вдруг... - это несколько не из нашей реальности
Гарантий одинаковости указателей на которые при одинаковости самих литералов стандартом не предусмотрено?
Совершенно неочевидно
это оптимизация компилятора
Ой как неочевидно. std::hash для const char* нет - получите сравнение указателей со всеми вытекающими
Которая, при отключении, например, приведет к некорректному поведению потенциально?
все не так, любой член твоей команды может положить туда все что угодно, в том числе ссылку на протухший std::string
и вопрос номер 2: причем здесь корутины? или это в каком-то другом контексте?
Вроде были реализации umap со строго constexpr ключами
Хочу заменить function на корутину или дать такую возможность
И вот мы вернулись к пропозалу экзекютеров... =) А точнее к тому что некоторые абстракции из него все-таки нужны.
Обсуждают сегодня