簡體   English   中英

從C初始化C ++結構

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

有關ISO CPP的更多信息。

您需要為您的結構分配內存:

    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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM