2016-08-30 2 views
1

Я пытаюсь использовать opencv C++ библиотека с другой библиотекой в ​​C. Таким образом, я определил структуру в качестве .hpp файла, который я добавил к .h из C библиотекиИнициализация структур C++ из 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 Um, компилировать без ссылки на g ++? Вопрос здесь не компиляции –

+0

@ Torbjörn Почему downvote? Вопрос не в компиляторе –

ответ

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

Yup, это просто вопрос инициализации myCPPStruct с помощью 'new myCPPStruct()' Это странно, потому что я думал, что я действительно пробовал это. Кроме того, я реорганизовал мою функцию для работы как ваш, так как в ней он просто возвращает инициализированную структуру, не передавая структуру самой функции. –

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); 

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

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

Feeww, до сих пор так хорошо ...

Теперь вы должны вставлять вам 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++ li brary.

В вашем конвейере компиляции 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. Вы должны скомпилировать код te C++ самостоятельно.

More on ISO CPP.

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); 
    } 

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

Смежные вопросы