[英]Initialisation of C++ structures from C
I'm trying to use opencv C++
library with another lib in C
. 我正在尝试将opencv C++
库与C
另一个库一起使用。 So I've defined a structure in an .hpp
file which I've added to the .h
of the C
library 因此,我在.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
In the .c
files the initializer for myCStruct calls initialize_myCPPStruct
which is defined in a .cpp
file somewhat as: 在.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);
}
But once it tries to allocate a value to mycppstruct->fs
, it gets a segmentation fault. 但是,一旦尝试为mycppstruct->fs
分配值,就会遇到分段错误。 I assume this is because there is no memory allocation in C, but I've tried 我认为这是因为C中没有内存分配,但是我已经尝试过
std::memset(stitcher->fs,0,sizeof(cv::FileStorage));
which also doesn't work as it can't parse cv:FileStorage
as void *
. 这也无法正常工作,因为它无法将cv:FileStorage
解析为void *
。
Will I have to use the deprecated C OpenCV library to make this work? 我是否必须使用已弃用的C OpenCV库才能进行此工作?
EDIT - More details about the compilation. 编辑-有关编译的更多详细信息。
For the C
lib, I recompile (without linking ie with the -c
option)all the .c
files where I've added C++
functions or structures using g++
while making sure I add the __cplusplus
guards in the .h
files. 对于C
库,我重新编译(不使用-c
选项链接)所有使用g++
添加C++
函数或结构的.c
文件,同时确保在.h
文件中添加__cplusplus
防护。 All the .c
files without C++
code already have .o
files compiled with gcc
. 所有没有C++
代码的.c
文件都已经具有使用gcc
编译的.o
文件。 I then compile the whole program with g++
while making sure to include the relevant library files. 然后,我使用g++
编译整个程序,同时确保包括相关的库文件。 There are no compiler errors. 没有编译器错误。
It seems the structure itself has not been created. 似乎结构本身尚未创建。
You might try this (or something similar): 您可以尝试以下操作(或类似方法):
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);
}
First, let me point out the sentence which confuse me. 首先,让我指出使我感到困惑的句子。
there is no memory allocation in C C中没有内存分配
Yes, there is. 就在这里。 Have a look to malloc
function. 看一下malloc
函数。
char *my_allocated_string = malloc(sizeof(char) * 42);
Here you are, you've allocated an array of character of size 42. 在这里,您已经分配了一个大小为42的字符数组。
Now, have a look to : mycppstruct = {};
现在,看看: mycppstruct = {};
That's not how you allocate a structure in C. You have to call... malloc()
! 那不是在C中分配结构的方式。您必须调用... malloc()
!
my_struct *s = malloc(sizeof(my_struct));
s->fs = 42;
Ok. 好。 Done. 做完了 Feels better. 感觉更好。
Well, first of all, you have to create a wrapper around your C++ code. 好吧,首先,您必须围绕您的C ++代码创建一个包装器。 Why ? 为什么呢 Because C++ allows multiple definition of a given function (also call symbol ) : 因为C ++允许对给定函数(也称为符号 )进行多次定义:
int my_func(int);
int my_func(char);
This is valid in C++. 这在C ++中有效。 But, think about it, how is the compiler able to let two functions with the same name exist ? 但是,考虑一下,编译器如何使两个具有相同名称的函数存在? Well it's not. 好吧,不是。 It uses a technique named mangling when evaluating the functions to create 2 different names. 在评估函数以创建2个不同的名称时,它使用一种称为mangling的技术。 Mangling is use on everything function and method. 整改用于所有功能和方法。 Event on single functions. 单功能事件。
C is not able (and willing) to create several functions with the same name. C无法(也不愿意)创建具有相同名称的多个函数。 Otherwise, you will experience a kind of function-already-implemented error. 否则,您将遇到一种功能已实现的错误。 When you declare : 当您声明:
int my_func(int);
the C compiler will create the symbol : my_func
. C编译器将创建符号: my_func
。 No mangling. 别吵了
To make both language interact, you need to reference to a symbol understandable by the C compiler. 为了使两种语言都可以交互,您需要引用C编译器可以理解的符号。 If you call my_func
from a C source file, the C compiler will look for my_func
symbol. 如果从C源文件调用my_func
,则C编译器将查找my_func
符号。 Bu since C++ will modify its my_func
symbol into something like _ZN9myfuncE
, the linkage will fail. 因为C ++将其my_func
符号修改为my_func
类的_ZN9myfuncE
,所以链接将失败。 That's why you have to says to the C++ compiler to not use mangling on the function you expose to C. That's why you need extern "C" { }
. 这就是为什么您必须对C ++编译器说不要对暴露给C的函数使用mangling。这就是为什么需要extern "C" { }
。
Feeww, so far so good... Feeww,到目前为止一切顺利...
Now you have to embed you C API into an extern "C"
block : 现在,您必须将C API嵌入到extern "C"
块中:
In my_c_api.h
: 在my_c_api.h
:
void my_func(int);
void my_func(char);
In my_c_api.cpp
: 在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); }
You compile it to create your C++ library. 您可以对其进行编译以创建C ++库。
In your C compilation pipeline, you link against your new C++ library and header files. 在C编译管道中,您链接到新的C ++库和头文件。 Then : 然后 :
#include "<path_to_my_c_api.h>"
void c(int i,char s)
{
my_func_i(i);
my_func_c(c);
}
You cannot compile C++ code with C compiler. 您不能使用C编译器来编译C ++代码。 You have to compile te C++ code independently. 您必须独立编译C ++代码。
You need to allocate the memory for your structure: 您需要为您的结构分配内存:
myCPPStruct = malloc(sizeof(myCPPStruct));
Use the above line instead of: 使用上面的行代替:
mycppstruct = {};
Also,since your function is passing in the pointer and allocating the memory internally you need to pass a pointer to the pointer or the allocation will not be passed back: 另外,由于您的函数正在传递指针并在内部分配内存,因此您需要将指针传递给指针,否则分配将不会被传递回:
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);
}
Or you could just change the above to: 或者,您可以将以上内容更改为:
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.