简体   繁体   English

从C初始化C ++结构

[英]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 ++代码。

More on ISO CPP. 有关ISO CPP的更多信息。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM