LINUX.ORG.RU

Вызов методов на С++ из С


0

0

Собственно, сабж. Возможно ли это? Суть в том, чтобы как-то вызвать конструктор класса (это же функция и она должна быть в таблице символов), получить указатель на экземпляр, а дальше this_copy->methodName(). Help!!!

anonymous

Ответ на: комментарий от dilmah

проблема вот в чем: ОС нужен указатель на сишную функцию, а у меня плюсовый класс. Я хотел сделать функцию, которая будет вызывать методы этого класса.

А extern "C" где должно быть? В сишном коде, типа extern "C" {#include "cpp_source.h}?

anonymous
()
Ответ на: комментарий от alex_custov

нет, у меня есть ОС, в которой нет разделения на процессы - он там один, слинкованный с ядром. Динамической линковки, собсно, нет.

Есть класс одноуровневой (да, есть и такое :)) файловой системы MyFS, экземпляров которой может быть несколько. При инициализации экземпляра, вызывающая сторона передает содержимое суперблока этой файловой системы, по которой объект строит список файлов.
Но ОС ставит требование - для реализации всех функций (mount, unmount, open etc) ей надо передать адреса функций с определенными параметрами. Так вот, задача состоит в том, чтобы подсунуть ОС сишные функции, которые будут работать с С++овым классом MyFS.

Класс пока только проектируется, так что исходников нет.

anonymous
()

> Возможно ли это?

Компиляторнонезависимо -- нет.

Для каждого конкретного комилятора -- легко, если нету статических классов и глобальных экземпляров. Если есть -- тоже легко, не чуть сложнее :-).

Можно слинковать ЦЕшную main() посредством g++, только, конечно, результирующая программа получится ЦППшная.

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

> А extern "C" где должно быть? В сишном коде

в плюсовом коде функция должна быть декларирована или объявлена с ним:

extern "C" int foo(int i);

dilmah ★★★★★
()
Ответ на: комментарий от Die-Hard

Компилятор - gcc. А как вызвать плюсовый метод, если у него меняется имя? Это имеется в виду под "Компиляторнонезависимо -- нет."?

anonymous
()
Ответ на: комментарий от dilmah

> сделай wrapper на С++. он должен экспортировать обычные функции (extern "C")

?

Не поможет, этот механизм работает "в другую сторону". ЦеППшные хедеры так не завернуть, компилятор выругается.

Die-Hard ★★★★★
()

// C++ code
extern "C" void* createObjectOfMyClass(int param) {
    return (void*) new MyClass(param);
}

extern "C" void methodName(void* obj) {
    ((MyClass*) obj)->methodName();
}

/* C code */
void* obj = createObjectOfMyClass(123);
methodName(obj);

Legioner ★★★★★
()
Ответ на: комментарий от Die-Hard

> Не поможет, этот механизм работает "в другую сторону". ЦеППшные хедеры так не завернуть, компилятор выругается.

Почему это?

Legioner ★★★★★
()
Ответ на: комментарий от dilmah

> в плюсовом коде функция должна быть декларирована или объявлена с ним: extern "C" int foo(int i);

Вообще, может, и прокатит, если нет статических классов/ глобальных экземпляров...

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

> Почему это?

Да, возможно, прокатит.

Опять же -- с точностью до того, что для корректной работы ЦеППшной проги main() должен быть, вообще говоря, ЦеППшным.

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

> А как вызвать плюсовый метод, если у него меняется имя?

Ну да: типа, посмотреть, как искажается, и вызвать.

Хотя надежнее, как тут рекомендовали, написать враппер. Хотя, проблемы после этого при линковке / выполнении могут начаться самые неожиданные.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Может быть, не совсем в тему, но есть такое замечательное средство SWIG, www.swig.org . Оно предназначено для вызова C++ из скриптовых языков. Когда-то я с ним копался, и у меня осталось ощущение, что написать С врапееры вокруг С++ методов на нём можно. Поскольку скриптовые языки не имеют интерфейса к С++, а имеют интерфейс только к С, привязка к ним происходит в три этапа:

- оборачиваем каждый С++ класс в набор С обёрток

- привязываем обёртку к скриптовому языку

- собираем в скриптовом языке класс из этих обёрток (если в нём вообще есть такое понятие, как класс)

Значит, нужно взять и выдрать из SWIG только первый этап этого процесса.

Конечно, ради одного класса это не стоит трудов, но если такой работы много, то Вы научитесь эти классы привязывать к С, как орешки щёлкать. А заодно и к другим языкам тоже.

den73 ★★★★★
()
Ответ на: комментарий от den73

А, и я забыл сказтаь самое главное - всё это SWIG делает автоматичеси, иногда требуется только небольшая помощь от пользователя :)

den73 ★★★★★
()
Ответ на: комментарий от Die-Hard

> Хотя надежнее, как тут рекомендовали, написать враппер. Хотя, проблемы после этого при линковке / выполнении могут начаться самые неожиданные.

Гм. А можно обоснование этого мощного заявления?

Утверждается, что

а) если враппер и сам плюсовый код содержатся в одном compilation unit-е - то вообще никаких проблем не может быть в принципе ("забыл написать extern "C"" проблемой линковки не считается)

б) если же это отдельные модули - то необходимым и достаточным условием является использование плюсового линкера; если программа собралась - то она будет работать нормально. Даже если сделать из myclass.cpp и myclass_wrapper.cpp разделяемую библиотеку, и потом подцепить из нее функции-врапперы не-C++-aware линкером - все равно все будет работать.

Если бы это было не так - то, скажем, встраивать интерпретаторы в плюсовые проги (и делать биндинги к плюсовым либам) было бы невозможно; однако ж я сам это делал и это таки работает надежно. Даже у меня, не говоря и всяких PyQt.

anonymous
()
Ответ на: комментарий от anonymous

> ...необходимым и достаточным условием является использование плюсового линкера;

Правильно!

Только зачем тогда получившееся называть "программой на Си"? Это получилась "программа на Си++"!

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.