Templates in C möglich machen?
-
fällt dir was auf?
ar -r libmyLib.a myc_wrapper.o myb_wrapper.ogcc -o mainnew mainnew.c -L lmyLib.aWie heißt die Lib denn nu wirklich?
-
und dort musst du die Templates auch auf konkrete Typen festlegen.
was irgendwo die Templates sinnlos macht... Aber scheint mir auch die einzige vernünftige Lösung zu sein. Wobei mir der Sinn des Ganzen immernoch nicht klar ist. Sollen die "User" halt nen C++-Compiler benutzen. Man kann nunmal nicht alles haben.
-
Die Lib heißt: libmyLib.a
Aber man kompiliert doch in gcc über -L lmylib.a.
Es klappt für keine der Varianten:
1 Variante:
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ück2 Variante
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ück3 Variante
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ück4 Variante
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
-
hmm....wo liegt mein fehler
?
-
1. Um eine statische Bibliothek hinzuzulinken, gibst Du entweder die Bibliothek selbst als Objekt (d.h. ohne zusätzliche Parameter) an (Variante 2) oder aber Du gibst das Verzeichnis der Bibliothek mit -L und die Bibliothek ohne lib und .a mit -l an (Variante 1 plus z.B. "-L.")
Also Variante 2
gcc -o mainnew mainnew.c libmyLib.aOder Variante 1 (korrigiert)
gcc -o mainnew mainnew.c -L. -lmyLib2. Die Undefined References kommen daher, dass der gcc (C-Compiler bzw. Linker) kein Bewusstsein über die C++-Standardbibliothek hat. Das heißt, Du musst diese zusätzlich mittels -lstdc++ angeben.
3. Die Multiple Definition von MyC<int>::print kommt nun daher, dass vollständige Spezialisierungen von Templates vollständige Definitionen sind, und diese sind per se nicht inline. Sprich, in jeder Übersetzungseinheit, in der Du MyC.h inkludierst, hast Du eine vollständige Definition von MyC<int>::print. Um das zu umgehen, kannst Du die Definition von MyC<int>::print mit inline kennzeichnen, oder die Definition in myb_wrapper.cpp auslagern und in MyC.h lediglich eine Deklaration stehenlassen.
-
Vielen Dank für das weitere Helfen. Verstehe....sehr interessant.
ich kompiliere nun über:
gcc -o mainnew mainnew.c libmyLib.a -lstdc++und meine MyC.h sieht so aus:
#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; }; inline 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 << mtx->data[i] << std::endl; } #endifaber selbst das inline wie Du vorgeschlagen hast löst das Problem
nicht:gcc -o mainnew mainnew.c libmyLib.a -lstdc++ 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 collect2: ld gab 1 als Ende-Status zurückHabe ich mit dem inline was falsch gemacht?
-
Ah, ich hatte natürlich die kompilation von my*_wrapper.cpp vegessen. Jetzt geht es. danke.
-
Ich bin sehr dankbar dass ich schon mal den ersten Teil kompilieren kann. Mir fehlt jetzt nur noch mein Ausgangssinn dass ich auch data verändern kann.
mir ist nicht klar warum die kompilation so fehlschlägt:g++ -c myb_wrapper.cpp myb_wrapper.cpp: In function »void myb_int_algorithm(WrapMyB_int, WrapMyC_int)«: myb_wrapper.cpp:14: Fehler: ungültiges static_cast vom Typ »WrapMyC_int« in den Typ »MyC<int>*«Mein Code sieht so aus:
//mainnew.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(); //constructor //MyB<int>().Algorithm(mtx); WrapMyB_int tmp = myb_int_create(); //constructor //myb_int_algorithm(tmp, mtx); //method 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); //other constructor //MyB<int>().Algorithm(mtx); WrapMyB_int tmp2 = myb_int_create(); //constructor myb_int_algorithm(tmp2, mtx2); //method myc_int_writetobuffer(mtx2, data); myc_int_delete(mtx2); //destructor myb_int_delete(tmp2); //destructor for (i = 0; i < 10; i++) printf("data[%d] = %d\n", i, data[i]); free(data); }//myb_wrapper.cpp
#include "myb_wrapper.h" #include "myc_wrapper.h" #include "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); MyC<int>* mc = static_cast<MyC<int>*> (arg); mb->Algorithm(mc); } void myb_int_delete(WrapMyB_int this_) { MyB<int>* mb = static_cast<MyB<int>*> (this_.ptr); delete mb; this_.ptr = NULL; }//myb_wrapper.h
#ifndef MYWB #define MYWB #ifdef __cplusplus extern "C" { #endif #include "myc_wrapper.h" 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 #endif//myc_wrapper.cpp
#include "myc_wrapper.h" #include "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) { /* ... */ } void myc_int_delete(WrapMyC_int this_) { MyC<int>* mc = static_cast<MyC<int>*> (this_.ptr); delete mc; this_.ptr = NULL; }//myc_wrapper.h
#ifndef MYWC #define MYWC #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 #endif#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; }; #endifund
#ifndef MyC_ #define MyC_ #include <iostream> #include <stdio.h> #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<> inline 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 << mtx->data[i] << std::endl; } #endifWarum kann ihc denn nicht casten?
-
argh...klar ich muss arg.ptr casten...
-
Wie setze ich denn aber das data array? bzw. den pointer in myc_wrapper.cpp ?
cih versuche das so:#include "myc_wrapper.h" #include "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_) { WrapMyC_int tmp; tmp.ptr = new MyC<int>(); tmp.ptr.data = data_; return tmp; } void myc_int_writetobuffer(WrapMyC_int this_, int* buffer) { /* ... */ } void myc_int_delete(WrapMyC_int this_) { MyC<int>* mc = static_cast<MyC<int>*> (this_.ptr); delete mc; this_.ptr = NULL; }und erhalte
g++ -c myc_wrapper.cpp myc_wrapper.cpp: In function »WrapMyC_int myc_int_create_1(int*)«: myc_wrapper.cpp:14: Fehler: Abfrage des Elementes »data« in »tmp.WrapMyC_int_::ptr«, das vom Nicht-Klassentyp »void*« ist
-
Schreib dir für MyC einen Konstruktor der einen Zeiger vom Typ T* als Argument hat und ggf. den Inhalt des übergebenen Arrays in sein eigenes Array kopiert. Den rufst du dann auf. Der Pointer in MyC sollte eh nicht public sein (Kapselung)