Подтвердить что ты не робот

Как вызвать конструктор С++ из C файла

Я импортировал эту программу, которая анализирует много сложного текста и написана на C. Мой собственный проект написан на С++.

Я на самом деле предполагал, что всякий раз, когда алгоритм синтаксического анализа нашел один из ключевых тегов, должен быть вызван один (многих) конструктор моего класса, так что у меня будет хорошая структура в конце txt, в результате процесса синтаксического анализа.

Здесь проблема: я изучил ООП с Java и начал работать с С++ с этим проектом, поэтому мне нужна небольшая помощь: как я могу вызвать конструктор С++ из моего файла парсера на основе C? Я уже проверил Интернет, но либо этот вопрос слишком тривиален, либо мое намеренное решение не работает;)

Спасибо за любые советы.

4b9b3361

Ответ 1

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

В заголовке вы должны написать:

 #ifdef __cplusplus
 #  define EXTERNC extern "C"
 #  define NOTHROW noexcept
 #else
 #  define EXTERNC
 #  define NOTHROW
 #endif

 /* Alias for your object in C that hides the implementation */
 typedef void* mylibraryname_mytype_t;

 /* Creates the object using the first constructor */
 EXTERNC mylibraryname_mytype_t mylibraryname_create_mytype() NOTHROW;

 /* Creates the object using the second constructor */
 EXTERNC mylibraryname_mytype_t mylibraryname_create_mytype_with_int(int val) NOTHROW;

 /* Frees the object, using delete */
 EXTERNC void mylibraryname_free_mytype(mylibraryname_mytype_t obj) NOTHROW;

Затем в исходном файле С++ вы можете:

 EXTERNC mylibraryname_mytype_t mylibraryname_create_mytype() NOTHROW {
   try {
     return static_cast<mylibraryname_mtype_t>(new MyType);
   }
   catch (...) {
     return nullptr;
   }
 }

 EXTERNC mylibraryname_mytype_t create_mytype_with_int(int val) NOTHROW {
   try {
     return static_cast<mylibraryname_mytype_t>(new MyType(val));
   }
   catch (...) {
       return nullptr;
   }
 }

 EXTERNC void mylibraryname_free_mytype(mylibraryname_mytype_t obj) NOTHROW {
   try {
     MyType* typed_obj = static_cast<MyType*>(obj);
     delete typed_obj;
   }
   catch (...) {
       // Ignore
   }
 }

Затем ваш C-код должен включать один и тот же заголовок и использовать определение из исходного файла С++ при привязке к сгенерированной библиотеке.

Обратите внимание, что приведенный выше код проглатывает исключения оптом. Для реального API вы должны предоставить способ указания ошибок вызывающему абоненту (например, путем возврата выделенного объекта через выходной параметр и возврата кода состояния) вместо того, чтобы просто подавлять их.

Изменить
Как отмечается в комментариях, "_t" является технически зарезервированным суффиксом (хотя вы должны быть в порядке, если ваши символы имеют префикс, который вряд ли будет использоваться стандартными библиотеками в будущем), поэтому просто убедитесь, что ваши символы включают в себя библиотеку имя в качестве префикса. Следует также отметить, что typedef, хотя и не требуется, предназначен для того, чтобы использовать объект более самодокументированным, чем необработанный "void *" повсюду.