从C初始化c++结构
Initialisation of C++ structures from C
我试图在C
中使用opencv 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库来完成此工作?
EDIT -关于编译的更多细节。
对于C
库,我重新编译(不与-c
选项链接ie)所有.c
文件,其中我使用g++
添加了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);
}
您需要为您的结构分配内存:
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;
Ok。完成了。感觉更好。
首先,你必须为你的c++代码创建一个包装器。为什么?因为c++允许给定函数的多个定义(也称为符号):
int my_func(int);
int my_func(char);
这在c++中是有效的。但是,想想看,编译器是如何让两个同名的函数存在的呢?其实不是。它在求值函数时使用名为mangling的技术来创建两个不同的名称。Mangling是用于所有功能和方法。单个函数的事件。
C不能(也不愿意)创建多个同名的函数。否则,您将遇到一种函数已经实现的错误。当你声明:
int my_func(int);
C编译器将创建符号:my_func
。没有碾压。
要使两种语言相互作用,需要引用C编译器可以理解的符号。如果从C源文件调用my_func
, C编译器将查找my_func
符号。但是,由于c++会将其my_func
符号修改为类似_ZN9myfuncE
的符号,因此链接将失败。这就是为什么你必须对c++编译器说而不是在你暴露给C的函数上使用mangling。这就是为什么你需要extern "C" { }
。
几个,到目前为止还好…
现在你必须嵌入你的C API到extern "C"
块:
In my_c_api.h
:
void my_func(int);
void my_func(char);
In 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的信息
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 如何重构类层次结构以避免菱形问题
- 如何在C++中序列化结构数据
- std::vector的包装器,使数组的结构看起来像结构的数组
- 没有为自己的结构调用列表推回方法
- 奇怪的结构&GCC&clang(void*返回类型)
- 在 c++ 中拥有一组结构的正确方法是什么?
- vscode g++链路故障:体系结构x86_64的未定义符号
- C++概念:如何使用'concept'检查模板化结构的属性?