从C初始化c++结构

Initialisation of C++ structures from C

本文关键字:结构 c++ 初始化      更新时间:2023-10-16

我试图在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的信息