У меня есть внешний интерфейс "C" для некоторого динамически загруженного кода. Для этого кода некоторые объекты являются непрозрачными дескрипторами, выраженными как void*
. Интерфейс выглядит так:
extern "C" {
void* get_foo() { Foo* foo = /* create and remember object */; return foo; }
int foo_get_bar(void* Foo) { return ((Foo*)foo)->bar(); }
}
Такой шаблон в значительной степени является стандартным способом взаимодействия с объектами C ++ через C-API, AFAIK. Но мне интересно, могу ли я пропустить приведение указателя?
Вызывающий код генерируется и связывается только с интерфейсом выше (он имеет свои собственные объявления функций). Таким образом, он эффективно генерирует код, подобный следующему:
void foo_get_bar(void*);
void* get_foo();
int do_something() { return foo_get_bar(get_foo()) };
Мы можем предположить, что вызывающий абонент использует код правильно (то есть он не пропускает неправильные указатели). Но, конечно, он не имеет понятия Foo
указатель.
Теперь можно изменить интерфейс на (более простой) вариант:
extern "C" {
int foo_get_bar(Foo* Foo) { return foo->bar(); }
}
Или есть небольшая разница между void*
и Foo*
на уровне компоновщика (может, например, размеры не совпадают?).
edit: Возможно, я вызвал некоторую путаницу с кодом вызывающей стороны в C. Нет кода C. Компилятора C не существует, и, следовательно, не требуется проверка типа C. Код вызывающего абонента генерируется и использует C-API. Поэтому для использования непрозрачной структуры мне нужно знать, как C-API представляет этот указатель после компиляции.