Я пытаюсь использовать 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++
, не заставляя включать соответствующие файлы библиотеки. Ошибок компилятора нет.
Кажется, что сама структура не была создана.
Вы можете попробовать это (или что-то подобное):
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);
}
new myCPPStruct()
что странно, потому что я думал, что я действительно попробовал это. Также я реорганизовал мою функцию, чтобы она работала как ваша, так как она просто возвращает инициализированную структуру без передачи структуры самой функции.
Вы должны выделить память для своей структуры:
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;
}
Во-первых, позвольте мне указать на предложение, которое меня смущает.
в 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++ самостоятельно.