Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Templates in C möglich machen?

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 <
000
18.01.2010, 15:27 Uhr
~Grupto
Gast


Hallo allerseits,

ich würde mich gerne informieren was ich für eine Möglichkeit habe C++ Templates
in C nutzbar zu machen.

*\ Ich habe einen funktionsfähigen Code der von jemandem anderen programmiert wurde und der über C kompiliert wird. Also rein C ist. Nennen wir diesen CODE_OTHER

*\ Dann habe ich meinen Code der C++ basiert ist und Templates verwendet.
Nennen wir diesen CODE_MY

*\ Jetzt möchte ich innerhalb CODE_OTHER meinen code also CODE_MY nutzbar machen.

Ich habe angenfangen in CODE_OTHER funktionen zu schreiben die ein Mapping zwischen den Datenstrukturen schafft. Jetzt komme ich aber an eine Stelle wo ich
eine Template-basierte klasse aus CODE_MY instantiieren will/muss.

Ich weiß hier nicht was ich tun kann/soll: Ich habe mich informiert es aber nicht genau verstanden:
-> Irgendwie gibt es eine Möglichkeit in CODE_MY über extern C interface funktionen an CODE_MY zu bieten. Dann CODE_MY als shared library zu kompilieren
und anschließend das Object-file von CODE_OTHER gegen das Object-file von CODE_MY zu linken.

Klappt das so oder kann mir jemand noch genauere angaben geben? Ich finde auch keine Minimalbeispiele diesbezüglich. ich würde mich sehr freuen wenn mir hier jemand helfen könnte.

Danke
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
18.01.2010, 18:25 Uhr
0xdeadbeef
Gott
(Operator)


Schreib deinen Code in C++, aber exportiere ein C-Interface. Beispielsweise:

C++:
/* c-bridge.h */
#ifndef INCLUDED_C_BRIDGE_H
#define INCLUDED_C_BRIDGE_H

#ifndef __cplusplus
extern "C" {
#endif

void print_hello(void);

#ifndef __cplusplus
}
#endif

#endif



C++:
// c-bridge.cc

#include "c-bridge.h"

#include <iostream>

void print_hello(void) {
  std::cout << "Hello, world." << std::endl;
}



C++:
/* main.c */
#include "c-bridge.h"

int main(void) {
  print_hello();

  return 0;
}


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

Dieser Post wurde am 18.01.2010 um 18:26 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
18.01.2010, 18:30 Uhr
~Grupto
Gast


Danke schonmal doch richtig verstanden hab ichs für mein problem noch nicht...

Wie schaffe ich es Algorithm statt auf mtx auf *data laufen zu lassen?

Ich muss doch dazu in CODE_MY eine funktion schreiben die *data entgegennimmt und die umwandlung macht? und dann ncoh eine zusätzliche funktion um Algorithm aufzurufen. Aber dazu musss ich ja die main() in CODE_MY verändern oder nicht?



C++:
// This is my C++ Programm
#include <iostream>
#include <string.h>
template<class T> class MyC
{
    public:
        MyC<T>() {
                data = new T[10];
                memset(data, 0, 10*sizeof(T));
        }
        ~MyC<T>() { delete [] data; }
        void print(MyC<int>* mtx);
        T* data;
};
template <> void
MyC<int>::print(MyC<int>* mtx)
{
   // Hier z.B. mtx ausgeben oder andere
   // Dinge mit mtx tun...
     for (int i = 0; i <10; i++)
        std::cout << i << std::endl;
}
template<class T> class MyB
{
        public:
                MyB<T>() {
                        mydata = new T[10];
                }

                void Algorithm(MyC<T>* mtx) {
                        // do something with mtx
                        mtx->print(mtx);
                        memcpy(mtx->data,mydata,10*sizeof(T));
                }
                T* mydata;
};
int main()
{
        MyC<int>* mtx = new MyC<int>();
        MyB<int>().Algorithm(mtx);
        delete mtx;
}



Hier mal das C programm CODE_OTHER welches eben z.B. die data struktur hat.


C++:
/*
* This is my C-Program
* */


#include "stdlib.h"

int main()
{
        double* data = calloc(10, sizeof(double));


        free(mydata);
}



Und wie schaffe ich es jetzt eine verbindung zwischen beiden herzustellen.
Also *data über
MyC<int>::print(MyC<int>* mtx)
auszugeben?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
18.01.2010, 19:00 Uhr
0xdeadbeef
Gott
(Operator)


Äh...du kannst sowieso nur eine main haben.

Ansonsten ist die Anbindung eine Designfrage, auf die es viele Antworten gibt - abhängig vom use case. Eine allgemeine Technik ist, das Interface der Klasse stumpf als stub-Funktionen nach außen zu reichen, etwa könnte eine Anbindung für

C++:
class A {
public:
  A(int);

  int x() const;
  void x(int);

private
  int x_;
};


so aussehen:

C++:
void *A_new(int x) {
  try {
    return static_cast<void*>(new A(x));
  } catch(...) {}

  return NULL;
}

void A_delete(void *a) {
  delete static_cast<A*>(a);
}

int A_get_x(void *a) {
  return static_cast<A*>(a)->x();
}

void A_set_x(void *a, int x) {
  static_cast<A*>(a)->x(x);
}


Templates wirst du allerdings in C nicht 1 zu 1 abgebildet kriegen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
19.01.2010, 23:28 Uhr
~Grupto
Gast


Also ich habe jetzt folgenden code:

Ich habe C++ code:
// MyC.h

C++:

#ifndef MyC_
#define MyC_

#include <iostream>

template<class T> class MyC
{
    public:
    MyC<T>() {
        data = new T[10];
        memset(data, 0, 10*sizeof(T));
    }
    ~MyC<T>() { delete [] data; }
    void print(MyC<int>* mtx);
    T* data;
};

template <> void
MyC<int>::print(MyC<int>* mtx)
{
   // Hier z.B. mtx ausgeben oder andere
   // Dinge mit mtx tun...
     int a;
     for (int i = 0; i <10; i++)
        std::cout << mtx->data[i] << std::endl;
}

#endif



//MyB.h

C++:
#ifndef MyB_
#define MyB_

#include "MyC.h"

template<class T> class MyB
{
    public:
        MyB<T>() {
            mydata = new T[10];
        }
        // do something with mtx
        void Algorithm(MyC<T>*& mtx) {
            for (int i= 0; i < 10; i++)
                mtx->data[i] = i;

            mtx->print(mtx);
            memcpy(mtx->data,mydata,10*sizeof(T));
        }
        T* mydata;
};

#endif



Und so wie ich es vertanden habe brauche ich für diese Klassen jetz wrapper:
Also cpp-wrapper:
// myb_wrapper.h

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

    typedef struct WrapMyB_int_
    {
        void* ptr;
    } WrapMyB_int;
    
    WrapMyB_int myb_int_create(void);
    void myb_int_algorithm(WrapMyB_int this_, WrapMyC_int arg);
    void myb_int_delete(WrapMyB_int this_);
    
#ifdef __cplusplus
} /*end extern "C"*/
#endif



die myb_wrapper.cpp

C++:
#include "myb_wrapper.h"
#include "myc_wrapper.h"
#include "C++/MyB.h" //MyB<T>

WrapMyB_int myb_int_create(void)
{
    WrapMyB_int tmp;
    tmp.ptr = new MyB<int>();
    return tmp;
}
void myb_int_algorithm(WrapMyB_int this_, WrapMyC_int arg)
{
    MyB<int>* mb = static_cast<MyB<int>*> (this_.ptr);
    //mb->Algorithm(arg);
}
void myb_int_delete(WrapMyB_int this_)
{
    MyB<int>* mb = static_cast<MyB<int>*> (this_.ptr);
    delete mb;
    this_.ptr = NULL;
}


und analog:
//myc_wrapper.h

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

    typedef struct WrapMyC_int_
    {
        void* ptr;
    } WrapMyC_int;

    WrapMyC_int myc_int_create(void);
//     WrapMyC_int myc_int_create_1(int* data);
//     void myc_int_writetobuffer(WrapMyC_int this_, int* buffer);
    void myc_int_delete(WrapMyC_int this_);

#ifdef __cplusplus
} /*end extern "C"*/
#endif


und die cpp myc_wrapper.cpp

C++:
#include "myc_wrapper.h"
#include "C++/MyC.h" //MyC<T>

WrapMyC_int myc_int_create(void)
{
    WrapMyC_int tmp;
    tmp.ptr = new MyC<int>();
    return tmp;
}
// WrapMyC_int myc_int_create_1(int* data)
// {
//
// }
// void myc_int_writetobuffer(WrapMyC_int this_, int* buffer)
// {
//         ||MLC||
// }
void myc_int_delete(WrapMyC_int this_)
{
    MyC<int>* mc = static_cast<MyC<int>*> (this_.ptr);
    delete mc;
    this_.ptr = NULL;
}


Jetzt kompiliere ich folgendes:

Code:
g++ -c myb_wrapper.cpp
g++ -c myc_wrapper.cpp


und erhalte objekte davon.
Ich baue mir eine statische library über


Code:
ar -r libmyLib.a myc_wrapper.o myb_wrapper.o



Jetzt habe cih meinen C-Code:
//mainnew.c

C++:
//main.c
#include "myc_wrapper.h"
#include "myb_wrapper.h"

#include "stdlib.h"

int main()
{
    int i;
    int* data = calloc(10, sizeof(int));

    for (i = 10; i > 0; i--)
        data[10-i] = i;
        
    /*...*/
    //MyC<int> * mtx = new MyC<int>();
    WrapMyC_int mtx = myc_int_create(); //konstruktor

    //MyB<int>().Algorithm(mtx);        
    WrapMyB_int tmp = myb_int_create(); //konstruktor
    //myb_int_algorithm(tmp, mtx);        //methode

    myc_int_delete(mtx);                //destruktor
    myb_int_delete(tmp);                //destruktor

    /*...*/
//     //MyC<int>* mtx = convert_data_to_MyC(data);
//     WrapMyC_int mtx2 = myc_int_create_1(data); //anderer konstruktor
//    
//     //MyB<int>().Algorithm(mtx);
//     WrapMyB_int tmp2 = myb_int_create(); //konstruktor
//     myb_int_algorithm(tmp2, mtx2);        //methode
//     myc_int_writetobuffer(mtx2, data);  
//    
//     myc_int_delete(mtx2);                //destruktor
//     myb_int_delete(tmp2);                //destruktor
//    
//     for (i = 0; i < 10; i++)
//         printf("data[%d] = %d\n", i, data[i]);
    
    free(data);
}



Die Lib heißt: libmyLib.a

Man kompiliert doch in gcc über -L lmylib.a.

Es klappt für keine der Varianten:

1 Variante:

Code:
gcc -o mainnew mainnew.c -lmyLib
warning: no newline at end of file
/usr/bin/ld: cannot find -lmyLib.a
collect2: ld gab 1 als Ende-Status zurück



2 Variante

Code:
gcc -o mainnew mainnew.c libmyLib.a
mainnew.c:42:2: warning: no newline at end of file
libmyLib.a(myb_wrapper.o): In function `MyC<int>::print(MyC<int>*)':
myb_wrapper.cpp:(.text+0xf6): multiple definition of `MyC<int>::print(MyC<int>*)'
libmyLib.a(myc_wrapper.o):myc_wrapper.cpp:(.text+0x100): first defined here
libmyLib.a(myc_wrapper.o): In function `__static_initialization_and_destruction_0(int, int)':
myc_wrapper.cpp:(.text+0x23): undefined reference to `std::ios_base::Init::Init()'
libmyLib.a(myc_wrapper.o): In function `__tcf_0':
myc_wrapper.cpp:(.text+0x6c): undefined reference to `std::ios_base::Init::~Init()'
libmyLib.a(myc_wrapper.o): In function `myc_int_delete':
myc_wrapper.cpp:(.text+0x9c): undefined reference to `operator delete(void*)'
libmyLib.a(myc_wrapper.o): In function `myc_int_create':
myc_wrapper.cpp:(.text+0xb9): undefined reference to `operator new(unsigned int)'
myc_wrapper.cpp:(.text+0xe2): undefined reference to `operator delete(void*)'
libmyLib.a(myc_wrapper.o): In function `MyC<int>::print(MyC<int>*)':
myc_wrapper.cpp:(.text+0x126): undefined reference to `std::cout'
myc_wrapper.cpp:(.text+0x12b): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(int)'
myc_wrapper.cpp:(.text+0x133): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
myc_wrapper.cpp:(.text+0x13b): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
libmyLib.a(myc_wrapper.o): In function `MyC<int>::~MyC()':
myc_wrapper.cpp:(.text._ZN3MyCIiED1Ev[MyC<int>::~MyC()]+0x18): undefined reference to `operator delete[](void*)'
libmyLib.a(myc_wrapper.o): In function `MyC<int>::MyC()':
myc_wrapper.cpp:(.text._ZN3MyCIiEC1Ev[MyC<int>::MyC()]+0xf): undefined reference to `operator new[](unsigned int)'
libmyLib.a(myc_wrapper.o):(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
libmyLib.a(myb_wrapper.o): In function `__static_initialization_and_destruction_0(int, int)':
myb_wrapper.cpp:(.text+0x31): undefined reference to `std::ios_base::Init::Init()'
libmyLib.a(myb_wrapper.o): In function `__tcf_0':
myb_wrapper.cpp:(.text+0x7a): undefined reference to `std::ios_base::Init::~Init()'
libmyLib.a(myb_wrapper.o): In function `myb_int_delete':
myb_wrapper.cpp:(.text+0x93): undefined reference to `operator delete(void*)'
libmyLib.a(myb_wrapper.o): In function `myb_int_create':
myb_wrapper.cpp:(.text+0xaf): undefined reference to `operator new(unsigned int)'
myb_wrapper.cpp:(.text+0xd8): undefined reference to `operator delete(void*)'
libmyLib.a(myb_wrapper.o): In function `MyC<int>::print(MyC<int>*)':
myb_wrapper.cpp:(.text+0x11c): undefined reference to `std::cout'
myb_wrapper.cpp:(.text+0x121): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(int)'
myb_wrapper.cpp:(.text+0x129): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
myb_wrapper.cpp:(.text+0x131): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
libmyLib.a(myb_wrapper.o): In function `MyB<int>::MyB()':
myb_wrapper.cpp:(.text._ZN3MyBIiEC1Ev[MyB<int>::MyB()]+0xe): undefined reference to `operator new[](unsigned int)'
libmyLib.a(myb_wrapper.o):(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
collect2: ld gab 1 als Ende-Status zurück




3 Variante

Code:
gcc -o mainnew mainnew.c -libmyLib.a
mainnew.c:42:2: warning: no newline at end of file
/usr/bin/ld: cannot find -libmyLib.a
collect2: ld gab 1 als Ende-Status zurück




4 Variante

Code:
gcc -o mainnew mainnew.c -L libmyLib.a
mainnew.c:42:2: warning: no newline at end of file
/tmp/cc2XoFP3.o: In function `main':
mainnew.c:(.text+0x57): undefined reference to `myc_int_create'
mainnew.c:(.text+0x6b): undefined reference to `myb_int_create'
mainnew.c:(.text+0x7f): undefined reference to `myc_int_delete'
mainnew.c:(.text+0x8a): undefined reference to `myb_int_delete'
collect2: ld gab 1 als Ende-Status zurück




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



Code:
gcc -c mainnew.c
g++ -o mainnew mainnew.o -L. -lmyLib


oder

Code:
gcc -o mainnew mainnew.c -L. -lmyLib -lstdc++


...und du musst deine Headerabhängigkeiten aufräumen sowie die vollständige Konkretisierung von MyC<int>::print(MyC<int>*) in eine eigene Übersetzungseinheit auslagern, um eine mehrfache Symboldefinition auszuschließen. std::memset befindet sich in <cstring>, wobei man in C++ eher std::fill aus <algorithm> benutzen würde - es kann ja durchaus mal sein, dass T ein komplexer Datentyp ist, und dann wäre es nur mäßig sinnvoll, beispielsweise den Zeiger auf die vtbl mit Nullen zu überschreiben.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 20.01.2010 um 14:20 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ 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: