2016-08-30 2 views
1

Ich versuche, Opencv C++ Bibliothek mit einer anderen Bibliothek in C zu verwenden. Also habe ich eine Struktur in einer .hpp-Datei definiert, die ich die .h der C Bibliothek hinzugefügt habeInitialisierung von C++ - Strukturen von C

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 

Im .c Dateien der Initialisierer für myCStruct initialize_myCPPStruct aufruft, die in einer .cpp-Datei definiert ist etwas wie:

void initialize_myCPPStruct(myCPPStruct * mycppstruct){ 
    mycppstruct = {}; 
    mycppstruct->fs = cv::FileStorage("file.txt", cv::FileStorage::READ); 
    mycppstruct->mat = cv::Mat(3,3,CV_8UC3); 
} 

Aber sobald es um einen Wert zu mycppstruct->fs zuzuordnen versucht, wird es einen Segmentation Fault. Ich nehme an, das liegt daran, dass es keine Speicherzuweisung in C, aber ich habe versucht,

std::memset(stitcher->fs,0,sizeof(cv::FileStorage));

die auch nicht, da es nicht cv:FileStorage als void * analysieren kann nicht funktioniert.

Muss ich die veraltete C OpenCV-Bibliothek verwenden, damit dies funktioniert?

BEARBEITEN - Weitere Details zur Kompilierung.

Für die C lib, ich neu kompilieren (ohne Verknüpfung dh mit der -c Option) alle .c Dateien, in denen ich C++ Funktionen oder Strukturen hinzugefügt haben g++ mit gleichzeitig dafür, ich die __cplusplus Wachen in den .h Dateien hinzufügen. Alle .c Dateien ohne C++ Code haben bereits .o Dateien kompiliert mit gcc. Ich kompiliere dann das gesamte Programm mit g++ und stelle sicher, dass die relevanten Bibliotheksdateien enthalten sind. Es gibt keine Compilerfehler.

+1

Wie sehen Sie Ihre C-Compiler erwarten C++ Code zu verarbeiten? –

+0

@ Torbjörn Um, kompilieren ohne Verknüpfung mit g ++? Das Problem hier ist nicht kompilieren –

+0

@ Torbjörn Warum der Downvote? Die Frage ist kein Compiler-Problem –

Antwort

2

Es scheint, dass die Struktur selbst nicht erstellt wurde.
Sie könnten diese (oder so ähnlich) versuchen:

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); 
} 
+0

Ja, es ging einfach darum, das myCPPStruct mit 'new myCPPStruct()' zu initialisieren. Das ist komisch, weil ich dachte, ich hätte es tatsächlich versucht. Außerdem habe ich meine Funktion so umgestaltet, dass sie wie Ihre Arbeit funktioniert, da sie einfach die initialisierte Struktur zurückgibt, ohne dass die Struktur an die Funktion selbst übergeben wird. –

2

Zunächst möchte ich den Satz hinweisen, die mich verwirren.

gibt es keine Speicherzuweisung in C

Ja, es gibt. Schauen Sie sich die malloc Funktion an.

char *my_allocated_string = malloc(sizeof(char) * 42); 

Hier werden Sie, haben Sie eine Reihe von Zeichen der Größe 42.

Jetzt zugewiesen, haben Sie einen Blick auf: mycppstruct = {};

Das ist nicht, wie man eine Struktur in C. Sie ordnen muss anrufen ... malloc()!

my_struct *s = malloc(sizeof(my_struct)); 
s->fs = 42; 

Ok. Erledigt. Fühlt sich besser an.


Nun, zuerst müssen Sie einen Wrapper um Ihren C++ - Code erstellen. Warum ?Da C++ mehrere Definition einer gegebenen Funktion ermöglicht (Anruf auch Symbol):

int my_func(int); 
int my_func(char); 

Dies gilt in C++. Aber denken Sie darüber nach, wie kann der Compiler zwei Funktionen mit dem gleichen Namen existieren lassen? Nun, ist es nicht. Es verwendet eine Technik namens mangling bei der Auswertung der Funktionen, um 2 verschiedene Namen zu erstellen. Mangling ist Gebrauch von allem Funktion und Methode. Ereignis bei einzelnen Funktionen.

C kann (und will) nicht mehrere Funktionen mit demselben Namen erstellen. Andernfalls werden Sie eine Art von Funktion-bereits-implementiert Fehler auftreten. Wenn Sie erklären:

int my_func(int); 

der C-Compiler wird das Symbol erstellen: my_func. Kein Mangel.

Damit beide Sprachen interagieren, müssen Sie auf ein Symbol verweisen, das für den C-Compiler verständlich ist. Wenn Sie my_func aus einer C-Quelldatei aufrufen, sucht der C-Compiler nach my_func Symbol. Bu da C++ sein my_func Symbol in etwas wie _ZN9myfuncE ändern wird, wird die Verknüpfung fehlschlagen. Deshalb müssen Sie dem C++ - Compiler zu nicht sagen Mangeln an der Funktion, die Sie an C. aussetzen. Deshalb brauchen Sie extern "C" { }.

Feeww, so weit, so gut ...

Jetzt haben Sie Sie C-API in ein extern "C" Block einzubetten:

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); } 

Sie kompilieren es, um Ihre C++ li zu erstellen blutig.

In Ihrer C-Kompilierungspipeline verknüpfen Sie Ihre neue C++ - Bibliothek und Header-Dateien. Dann:

#include "<path_to_my_c_api.h>" 

void c(int i,char s) 
{ 
    my_func_i(i); 
    my_func_c(c); 
} 

Sie können nicht C++ - Code mit C-Compiler kompilieren. Sie müssen te C++ - Code unabhängig kompilieren.

More on ISO CPP.

2

Sie müssen den Speicher für Ihre Struktur zuzuordnen:

myCPPStruct = malloc(sizeof(myCPPStruct)); 

Verwenden Sie die obige Zeile statt:

mycppstruct = {}; 

Da auch Ihre Funktion in dem Zeiger ist vorbei Wenn Sie den Speicher intern zuweisen, müssen Sie einen Zeiger an den Zeiger übergeben, andernfalls wird die Zuweisung nicht zurückgegeben:

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); 
    } 

Oder Sie könnten nur die oben ändern: