Инициализация структур C ++ из C

1

Я пытаюсь использовать opencv C++ библиотеку с другим lib в C Поэтому я определил структуру в файле .hpp который я добавил в .h библиотеки C

typedef struct {
  cv::FileStorage fs;
  cv::Mat mat;
} myCPPStruct;

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {    
    myCPPStruct * mycppstruct;    
} myCStruct;

void initialize_myCPPStruct(myCPPStruct * mycppstruct);

#ifdef __cplusplus
}
#endif

В файлах .c инициализатор для myCStruct вызывает initialize_myCPPStruct который определен в файле .cpp несколько как:

void initialize_myCPPStruct(myCPPStruct * mycppstruct){
  mycppstruct = {};
  mycppstruct->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
  mycppstruct->mat = cv::Mat(3,3,CV_8UC3);
}

Но как только он пытается выделить значение mycppstruct->fs, он получает ошибку сегментации. Я предполагаю, что это связано с тем, что в C нет выделения памяти, но я попытался

std::memset(stitcher->fs,0,sizeof(cv::FileStorage));

который также не работает, поскольку он не может разобрать cv:FileStorage как void *.

Должен ли я использовать устаревшую библиотеку C OpenCV, чтобы сделать эту работу?

EDIT - Подробнее о компиляции.

Для C lib я перекомпилирую (без ссылки, то есть с -c) все .c файлы, где я добавил C++ функции или структуры, используя g++, убедившись, что я добавляю __cplusplus охранники в .h файлы. Все файлы .c без C++ уже имеют файлы .o скомпилированные с помощью gcc. Затем я компилирую всю программу с помощью g++, не заставляя включать соответствующие файлы библиотеки. Ошибок компилятора нет.

  • 1
    Как вы ожидаете, что ваш компилятор C будет обрабатывать код C ++?
  • 0
    @ Torbjörn Хм, компилируй без связи с g ++? Проблема здесь не компилируется
Показать ещё 5 комментариев
Теги:
opencv

3 ответа

2
Лучший ответ

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

myCPPStruct* initialize_myCPPStruct()
{
  myCPPStruct* result;
  result = new myCPPStruct();
  result->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
  result->mat = cv::Mat(3,3,CV_8UC3);
  return (result);
}
  • 0
    Да, это был просто вопрос инициализации myCPPStruct с new myCPPStruct() что странно, потому что я думал, что я действительно попробовал это. Также я реорганизовал мою функцию, чтобы она работала как ваша, так как она просто возвращает инициализированную структуру без передачи структуры самой функции.
2

Вы должны выделить память для своей структуры:

    myCPPStruct = malloc(sizeof(myCPPStruct));

Используйте приведенную выше строку вместо:

    mycppstruct = {};

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

    void initialize_myCPPStruct(myCPPStruct** mycppstruct){
        if ( mycppstruct == NULL ) {
     //Abort as no address of the pointer to allocate passed
            return;
        }
        *myCPPStruct = malloc(sizeof(myCPPStruct));
        (*mycppstruct)->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
        (*mycppstruct)->mat = cv::Mat(3,3,CV_8UC3);
    }

Или вы можете просто изменить выше:

    myCPPStruct* initialize_myCPPStruct(void) {
        myCPPStruct* ptr = malloc(sizeof(myCPPStruct));
        ptr->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
        ptr->mat = cv::Mat(3,3,CV_8UC3);
        return ptr;
    }
2

Во-первых, позвольте мне указать на предложение, которое меня смущает.

в C отсутствует выделение памяти

Да, есть. Посмотрите на функцию malloc.

char *my_allocated_string = malloc(sizeof(char) * 42);

Вот вы, вы выделили массив символов размером 42.

Теперь взгляните на: mycppstruct = {};

Это не то, как вы выделяете структуру в C. Вы должны вызвать... malloc() !

my_struct *s = malloc(sizeof(my_struct));
s->fs = 42;

ОК. Готово. Чувствует себя лучше.


Ну, во-первых, вам нужно создать обертку вокруг вашего кода C++. Зачем? Поскольку C++ допускает множественное определение данной функции (также символ вызова):

int my_func(int);
int my_func(char);

Это справедливо в C++. Но, подумайте об этом, как компилятор может позволить использовать две функции с тем же именем? Ну, это не так. Он использует технику под названием mangling при оценке функций для создания двух разных имен. Mangling используется во всех функциях и методах. Событие по отдельным функциям.

C не может (и хочет) создавать несколько функций с тем же именем. В противном случае вы столкнетесь с какой-то функцией, уже реализованной ошибкой. Когда вы заявляете:

int my_func(int);

компилятор C создаст символ: my_func. Никакой манипуляции.

Чтобы заставить оба языка взаимодействовать, вам нужно ссылаться на символ, понятный компилятору C. Если вы вызываете my_func из исходного файла C, компилятор C будет искать символ my_func. Bu, поскольку C++ изменит свой символ my_func на что-то вроде _ZN9myfuncE, связь не удастся. Вот почему вы должны сказать компилятору C++, чтобы не использовать mangling для функции, которую вы показываете C. Для этого вам нужен extern "C" { }.

Полагаю, до сих пор так хорошо...

Теперь вам нужно встроить C API в внешний блок extern "C":

В my_c_api.h:

void my_func(int);
void my_func(char);

В my_c_api.cpp:

#include "my_c_api.h"

extern "C" void my_func_i(int i) { my_func(i); }
extern "C" void my_func_c(char c) { my_func(c); }

Вы скомпилируете его для создания библиотеки C++.

В вашем конвейере компиляции C вы ссылаетесь на свою новую библиотеку C++ и файлы заголовков. Затем:

#include "<path_to_my_c_api.h>"

void c(int i,char s)
{
    my_func_i(i);
    my_func_c(c);
}

Вы не можете скомпилировать код C++ с компилятором C. Вы должны скомпилировать код C++ самостоятельно.

Подробнее о ISO CPP.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню