Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » C++ code in C aufrufen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
09.11.2008, 05:56 Uhr
xyz



Hallo,
gibt es irgendwo howto wie man C++ Code/Bibliothek in C benutzen/aufrufen kann?

Viele Grüße
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
09.11.2008, 15:21 Uhr
0xdeadbeef
Gott
(Operator)


C++ beherrscht eine Menge Dinge, die C nicht kennt, direkt geht das also nicht. Man kann aber ein C-Interface um C++-Code herum schreiben, in etwa so:

C++:
/* C++-Header foo.hpp */

#ifndef INCLUDED_FOO_HPP
#define INCLUDED_FOO_HPP

struct foo {
  void bar();
};

#endif



C++:
/* C-Header c-compat/foo.h */

#ifndef INCLUDED_C_COMPAT_FOO_H
#define INCLUDED_C_COMPAT_FOO_H

#ifdef __cplusplus
extern "C" {
#endif

typedef void *foo_t;

foo_t new_foo();
void delete_foo(foo_t);

void foo_bar(foo_t);

#ifdef __cplusplus
}
#endif

#endif




C++:
/* Quellcode c-compat/foo.cpp */
#include "c-compat/foo.h"
#include "foo.hpp"

foo_t new_foo() {
  return reinterpret_cast<foo_t>(new foo());
}

void delete_foo(foo_t *obj) {
  delete reinterpret_cast<foo*>(obj);
}

void foo_bar(foo_t *obj) {
  reinterpret_cast<foo*>(obj)->bar();
}


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 09.11.2008 um 15:22 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
10.11.2008, 00:12 Uhr
~xyz
Gast


Wie würde man es mit g++ und gcc kompilieren und wie sieht der C Code aus?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
10.11.2008, 12:06 Uhr
xyz



Wie würde man es mit g++ und gcc kompilieren und wie sieht der C Code aus für dieses Beispiel:


C++:
#ifndef EXAMPLE_H
#define EXAMPLE_H

class Bar {
public:
    Bar();
    Bar(const Bar&);
    Bar(double);
    Bar(double, char *);
    Bar(int, int);
    Bar(char *);
    Bar(long);
    Bar(int);
    Bar(Bar *);

    void foo(const Bar&);
    void foo(double);
    void foo(double, char *);
    void foo(int, int);
    void foo(char *);
    void foo(long);
    void foo(int);
    void foo(Bar *);
    
    void spam(int x, int y=2, int z=3);
    void spam(double x, int y=2, int z=3);
};

void foo(const Bar&);
void foo(double);
void foo(double, char *);
void foo(int, int);
void foo(char *);
void foo(int);
void foo(long);
void foo(Bar *);

void spam(int x, int y=2, int z=3);
void spam(double x, int y=2, int z=3);

#endif




C++:
#include <iostream>

#include "example.h"

// Overloaded constructors for class Bar
Bar::Bar() {
    std::cout << "Called Bar::Bar()" << std::endl;
}

Bar::Bar(const Bar&) {
    std::cout << "Called Bar::Bar(const Bar&)" << std::endl;
}

Bar::Bar(double x) {
    std::cout << "Called Bar::Bar(double) with x = " << x << std::endl;
}

Bar::Bar(double x, char *y) {
    std::cout << "Called Bar::Bar(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl;
}

Bar::Bar(int x, int y) {
    std::cout << "Called Bar::Bar(int, int) with x, y = " << x << ", " << y << std::endl;
}

Bar::Bar(char *x) {
    std::cout << "Called Bar::Bar(char *) with x = \"" << x << "\"" << std::endl;
}

Bar::Bar(int x) {
    std::cout << "Called Bar::Bar(int) with x = " << x << std::endl;
}

Bar::Bar(long x) {
    std::cout << "Called Bar::Bar(long) with x = " << x << std::endl;
}

Bar::Bar(Bar *x) {
    std::cout << "Called Bar::Bar(Bar *) with x = " << x << std::endl;
}

// Overloaded member functions
void Bar::foo(const Bar& x) {
    std::cout << "Called Bar::foo(const Bar&) with &x = " << &x << std::endl;
}

void Bar::foo(double x) {
    std::cout << "Called Bar::foo(double) with x = " << x << std::endl;
}

void Bar::foo(double x, char *y) {
    std::cout << "Called Bar::foo(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl;
}

void Bar::foo(int x, int y) {
    std::cout << "Called Bar::foo(int, int) with x, y = " << x << ", " << y << std::endl;
}

void Bar::foo(char *x) {
    std::cout << "Called Bar::foo(char *) with x = \"" << x << "\"" << std::endl;
}

void Bar::foo(int x) {
    std::cout << "Called Bar::foo(int) with x = " << x << std::endl;
}

void Bar::foo(long x) {
    std::cout << "Called Bar::foo(long) with x = " << x << std::endl;
}

void Bar::foo(Bar *x) {
    std::cout << "Called Bar::foo(Bar *) with x = " << x << std::endl;
}

void Bar::spam(int x, int y, int z) {
    std::cout << "Called Bar::spam(int, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl;
}

void Bar::spam(double x, int y, int z) {
    std::cout << "Called Bar::spam(double, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl;
}

// Overloaded global methods
void foo(const Bar& x) {
    std::cout << "Called foo(const Bar& x) with &x = " << &x << std::endl;
}

void foo(double x) {
    std::cout << "Called foo(double) with x = " << x << std::endl;
}

void foo(double x, char *y) {
    std::cout << "Called foo(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl;
}

void foo(int x, int y) {
    std::cout << "Called foo(int, int) with x, y = " << x << ", " << y << std::endl;
}

void foo(char *x) {
    std::cout << "Called foo(char *) with x = \"" << x << "\"" << std::endl;
}

void foo(int x) {
    std::cout << "Called foo(int) with x = " << x << std::endl;
}

void foo(long x) {
    std::cout << "Called foo(long) with x = " << x << std::endl;
}

void foo(Bar *x) {
    std::cout << "Called foo(Bar *) with x = " << x << std::endl;
}

// Overloaded global spam() functions
void spam(int x, int y, int z) {
    std::cout << "Called spam(int, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl;
}

void spam(double x, int y, int z) {
    std::cout << "Called spam(double, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl;
}



 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
10.11.2008, 16:15 Uhr
0xdeadbeef
Gott
(Operator)


In C sähe das für das einfache Beispiel oben etwa so aus:

C++:
#include <c-compat/foo.h>

/* ... */

foo_t f = new_foo(); /* entspricht foo *f = new foo(); */
foo_bar(f); /* entspricht f->bar() */
delete_foo(f); /* entspricht delete f; */


Überladene Funktionen wirst du im C-Interface mit eindeutigen Namen versehen müssen, außerdem musst du darauf achten, dass keine Exceptions nach außen geworfen werden - die kennt C nämlich auch nicht. Default-Parameter kennt C ebenfalls nicht, die wirst du also entweder explizit angeben oder Stub-Funktionen schreiben müssen, in etwa so:

C++:
void foo_bar0(foo_t obj) {
  reinterpret_cast<foo*>(obj)->bar();
}

void foo_bar1(foo_t obj, int x) {
  reinterpret_cast<foo*>(obj)->bar(x);
}


Im Endeffekt läuft es darauf hinaus, dass das Interface zwar in C++ implementiert wird, aber nach außen für C verständlich sein muss. Also: Keine Funktionsüberladung, keine Exceptions, keine sichtbaren C++-Typen etc., und für den C++-Compiler muss extern "C" { } um die Deklarationen stehen, damit die Namen nicht gemangelt werden. Deshalb auch der

C++:
#ifdef __cplusplus
extern "C" {
#endif

// ...

#ifdef __cplusplus
}
#endif


-Kram im Header.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 10.11.2008 um 16:16 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
12.11.2008, 13:23 Uhr
~xyz
Gast


Danke, aber wie kompeiliert man das ganze unter linux?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
12.11.2008, 14:24 Uhr
0xdeadbeef
Gott
(Operator)


.cpp mit g++, .c mit gcc, üblicherweise. Ansonsten halt wie gehabt in .o-Dateien übersetzen und die zu was immer du am Ende haben willst zusammenlinken.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
13.11.2008, 03:34 Uhr
~xyz
Gast


Wenn ich es versuche zu kompilieren bekomme ich folgenden Fehler:

Code:
$ g++ -c foo.cpp -o foo.o
$ gcc -c -o main.o main.c
$ gcc -o main main.o
main.o: In function `main':
main.c:(.text+0x1d): undefined reference to `new_foo'
main.c:(.text+0x2b): undefined reference to `foo_bar'
main.c:(.text+0x39): undefined reference to `delete_foo'
collect2: ld returned 1 exit status



Ich habe alles in einem Ordner gepackt und #ifndef, #define und #include habe ich angepasst.

Main.c sieht wie folgt aus:

Code:
#include "foo.h"

int main() {
  foo_t f = new_foo(); /* entspricht foo *f = new foo(); */
  foo_bar(f); /* entspricht f->bar() */
  delete_foo(f); /* entspricht delete f; */
}



Was mache ich falsch?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
13.11.2008, 16:55 Uhr
0xdeadbeef
Gott
(Operator)


Das ist ja auch kein Wunder, wenn du bei

C++:
$ gcc -o main main.o


vergisst, foo.o dazuzulinken:

C++:
$ gcc -o main main.o foo.o



Übrigens gibt main in C nicht automatisch 0 zurück, du brauchst in main.c also noch ein return 0; (Und ganz streng genommen garantiert C int main(void) als erlaubte Signatur für main, nicht int main() - aber ich kenne keinen Compiler, der int main() ablehnt).
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 13.11.2008 um 16:56 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
14.11.2008, 02:56 Uhr
~xyz
Gast


Leider bekomme ich es immer noch nicht kompiliert:

Code:
$ g++ -c foo.cpp -o foo.o
$ gcc -c -o main.o main.c
$ gcc -o main main.o foo.o
main.o: In function `main':
main.c:(.text+0x2b): undefined reference to `foo_bar'
main.c:(.text+0x39): undefined reference to `delete_foo'
foo.o: In function `new_foo':
foo.cpp:(.text+0xc): undefined reference to `operator new(unsigned int)'
foo.o: In function `delete_foo(void**)':
foo.cpp:(.text+0x24): undefined reference to `operator delete(void*)'
foo.o: In function `foo_bar(void**)':
foo.cpp:(.text+0x3c): undefined reference to `foo::bar()'
foo.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status



Ich habe main.c wie folgt verändert:

Code:
#include "foo.h"

int main(void) {
  foo_t f = new_foo(); /* entspricht foo *f = new foo(); */
  foo_bar(f); /* entspricht f->bar() */
  delete_foo(f); /* entspricht delete f; */
  return 0;
}



Was mache ich falsch?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: