[英]Initialisation of C++ structures from C
我正在嘗試將opencv C++
庫與C
另一個庫一起使用。 因此,我在.hpp
文件中定義了一個結構,該結構已添加到C
庫的.h
中
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庫才能進行此工作?
編輯-有關編譯的更多詳細信息。
對於C
庫,我重新編譯(不使用-c
選項鏈接)所有使用g++
添加C++
函數或結構的.c
文件,同時確保在.h
文件中添加__cplusplus
防護。 所有沒有C++
代碼的.c
文件都已經具有使用gcc
編譯的.o
文件。 然后,我使用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);
}
首先,讓我指出使我感到困惑的句子。
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 ++中有效。 但是,考慮一下,編譯器如何使兩個具有相同名稱的函數存在? 好吧,不是。 在評估函數以創建2個不同的名稱時,它使用一種稱為mangling的技術。 整改用於所有功能和方法。 單功能事件。
C無法(也不願意)創建具有相同名稱的多個函數。 否則,您將遇到一種功能已實現的錯誤。 當您聲明:
int my_func(int);
C編譯器將創建符號: my_func
。 別吵了
為了使兩種語言都可以交互,您需要引用C編譯器可以理解的符號。 如果從C源文件調用my_func
,則C編譯器將查找my_func
符號。 因為C ++將其my_func
符號修改為my_func
類的_ZN9myfuncE
,所以鏈接將失敗。 這就是為什么您必須對C ++編譯器說不要對暴露給C的函數使用mangling。這就是為什么需要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 ++庫。
在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 ++代碼。
您需要為您的結構分配內存:
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.