C Wrapper Fehler



  • Moin!

    Ich habe ein C++ Programm, auf dessen Funktionen man auch Zugriff mittles C Programm braucht.
    Also habe ich mir ein Testprogramm geschrieben, um die "Wrapper" auszutesten:

    MyTest.h

    #ifndef MYTEST_H_
    #define MYTEST_H_
    
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    class MyTest {
    public:
    	MyTest();
    
    	string getBar();
    	int getFoo();
    
    	void setBar(string);
    	void setFoo(int);
    
    private:
    	int foo;
    	string bar;
    };
    
    #ifndef __cplusplus
    extern "C"{
    #endif
    
    	struct MyTest;
    	struct MyTest* getInstance();
    	void setFoo(struct MyTest*, int);
    	int getFoo(struct MyTest* );
    
    	void setBar(struct MyTest*, const char*);
    	const char* getBar(struct MyTest*);
    
    #ifndef __cplusplus
    }
    #endif
    
    #endif /* MYTEST_H_ */
    

    MyTest.cpp

    #include "MyTest.h"
    
    MyTest::MyTest() {
    	// TODO Auto-generated constructor stub
    
    }
    
    string MyTest::getBar()
    {
    	return this->bar;
    }
    
    int MyTest::getFoo()
    {
    	return this->foo;
    }
    
    void MyTest::setBar(string x)
    {
    	this->bar = x;
    }
    
    void MyTest::setFoo(int x)
    {
    	this->foo = x;
    }
    
    #ifndef __cplusplus
    extern "C" {
    #endif
    
    struct MyTest* getInstance()
    {
    	return new MyTest;
    }
    
    void setFoo(struct MyTest* ptr, int x) {
    	ptr->setFoo(x);
    }
    
    int getFoo(struct MyTest* ptr) {
    	return ptr->getFoo();
    }
    
    void setBar(struct MyTest* ptr, const char* x)
    {
    	ptr->setBar(x);
    }
    
    const char* getBar(struct MyTest* ptr)
    {
    	return (ptr->getBar()).c_str();
    }
    
    #ifndef __cplusplus
    }
    #endif
    

    main.cpp

    #include "MyTest.h"
    #include <stdio.h>
    
    int main(void)
    {
    	struct MyTest *test;
    
    	test = getInstance();
    
    	setFoo(test, 12345);
    	printf("Foo: %d \n", getFoo(test));
    
    	setBar(test, "bla");
    	printf("Ausgabe von Bar: %s \n", getBar(test));
    
    	return 0;
    }
    

    Die .h und .cpp-Files habe ich mit dem g++ Compiler übersetzt und die main.cpp mit dem gcc! DAS hat funktioniert.

    jetzt wollte ich diese Wrapperfunktionen in ein anderes Projekt "übertragen"!

    Wenn ich jetzt mein neues Projekt compiliere, dann gibt es spätestens beim gcc compiler 10.000 fehlermeldungen, dass er die Datei "iostream", "string", "map" etc. nicht findet! Also genau die C++ Sachen!

    Kann sich jemand vorstellen, wo dran es liegt?!

    gruß sdy



  • die c++-standardbibliothek ist nicht dazugelinkt worden.
    musst noch -lstdc++ oser sowas ähnliches dem gcc als compileroprion spendieren.



  • okay..habe jetzt 2 Verfahren probiert.

    1. Der Fehler trat beim zweiten Mal auf, da die Datei die Endung ".c" hatte. Als ich sie in .cpp geändert hatte, lief alles glatt.
    Kann ja aber nicht sein, dass der gcc-Compiler nur Dateien mit .cpp-Endung frisst.

    Also habe ich der Datei wieder die Endung ".c" gegeben und
    2. habe nach der C++-Standardbibliothek gesucht: libstdc++.so.6
    (Die wird es doch sein,oder?!)

    Aber irgendwie habe ich immer nioch den gleichen Fehler? Wie linke ich die .so Datei nun dazu?

    Ich habe schon verschiedenes probiert:

    -libstdc++.so.6
    -lstdc++.so.6
    -Llibstdc++.so.6
    -Lstdc++

    und und und...kann mir jemand sagen, wo ich den Fehler beim Linken mache?!

    Gruß Sdy



  • .c sieht der GCC als C-Code an und .cpp als C++-Code. Ob du gcc oder g++ aufrufst ist dabei egal, da g++ nur ein gcc-Frontend ist, welches die Linkeroptionen entsprechend setzt.

    Wenn die Datei also foo.c heißt, solltest du da nur C-Code reinpacken und nicht iostream und co inkludieren (auch nicht indirekt in einem anderen Header)

    Und wenn die Library libFOO.so heißt, dann linkt man mit -lFOO (lib und .so lässt man weg). Siehe GCC Handbuch.



  • ja ist klar. aber dann verstehe ich nicht, wie man c-wrapperfunktionen für c++-methoden schreiben soll?!
    Die Datei, die die Wrapper beinhaltet, muss ja teils C und teils C++ sein und dann muss wiederum die Datei mit dem C Code ja irgendwie Zugriff auf diese Funktionen haben. 😕



  • Du musst die Header eben strikt trennen

    // foo.hpp
    class foo {
      int i;
    public:
      foo(int i) : i(i) { }
      int get() const { return i; }
      void set(int j) { i = j; }
    };
    
    // foo-wrapper.h - C Wrapper
    #ifndef FOO_H
    #define FOO_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    typedef void* foo_t;
    foo_t foo_create(int i);
    foo_t foo_copy(foo_t f);
    void foo_destruct(foo_t f);
    void foo_assign(foo_t a, foo_t const from);
    int foo_get(foo_t self);
    void foo_set(foo_t self, int);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    
    // foo-wrapper.cpp
    #include "foo.hpp"
    #include "foo-wrapper.h"
    
    extern "C" {
      foo_t foo_create(int i) { return static_cast<foo_t>(new foo(i)); }
      int foo_get(foo_t self) { return static_cast<foo*>(self)->get(); }
      //...
    }
    
    // main.c
    #include "foo-wrapper.h"
    
    int main() {
      foo_t f = foo_create(10);
      return foo_get(f);
    }
    


  • // foo-wrapper.cpp
    #include "foo.hpp"
    #include "foo-wrapper.h"
    
    extern "C" {
      foo_t foo_create(int i) { return static_cast<foo_t>(new foo(i)); }
      int foo_get(foo_t self) { return static_cast<foo*>(self)->get(); }
      //...
    }
    
    // main.c
    #include "foo-wrapper.h"
    
    int main() {
      foo_t f = foo_create(10);
      return foo_get(f);
    }
    

    Aber genau hier kommt es doch wieder zum klinsch!
    In der foo-wrapper.cpp wird die Klasse mittels foo.hpp eingebunden und später dann indirekt in die main.c! Ich sehe da jetzt irgendwie nicht so den Unterschied zu meiner Lösung, außer, dass ich die C UND C++ Deklaration in eine Datei und die Definition beider Spachen in die andere Datei packe.



  • bei meiner Lösung sieht der C Teil nichts vom C++ Teil und das ist der fundamentale Unterschied. Ein C-Compiler kann mit C++ idR nicht sehr viel anfangen.



  • Aaah ok! 😃
    nun hab ich es! Vielen Dank. Ich probier mal mein Glück...



  • gibt es eine möglichkeit, die beiden header (per bedingter compilierung) in einer header zusammenzufassen?!



  • #ifdef __cplusplus
    
    class Bla{
    public:
    int getFoo();
    .
    .
    }
    #endif
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    [..]
    int getFoo(...)
    
    #ifdef __cplusplus /* C Zugriffe */
    }
    #endif
    

    Wo sind da meine Fehler? Der Header soll von beiden Compilern gelesen werden können!


Anmelden zum Antworten