-
Using C in C++
Hello all,
I'm using some libraries made in C, in my C++ program. I must design a library that will basically encapsulate this C library. There is a test1.c example of the use of the library. I worked so far 2 classes:
Code:
class base_lvl1;
class base_lvl2;
each in it's own .h,.cpp pair, denoted here by base_lvl1.h(.cpp) and base_lvl2.h(.cpp). The only include test1.c have is original.h.
I made a base_inc.h file to include the needed include files. The files include list are below:
Code:
//base_inc.h
#include "base_lvl2.h"
...
//base_lvl2.h
#include "base_lvl1.h"
..
//base_lvl1.h
#include "original.h"
I've searched around and found I need the extern C directive, and original.h already does that.
My first test (test1.cpp) was a copy of test1.c, and it compiled. test1.cpp #include original.h
My second test (test2.cpp) was the creation of class base_lvl1 and the substitution of it's associated not encapsulated data by it, and it compiles. test2.cpp #include base_lvl1.h.
My third test (test3.cpp) was the creation of class base_lvl2 and the substitution of it's associated not encapsulated data by it, and it does not compile. test3.cpp #include base_lvl2.h
To explain exactly where the error goes:
- I can generate base_lvlx.o
- I can't compile test3.cpp with the line
Code:
$(CXX) -o $@ $< $(I) $(LIB) $(LIB2) $(CXXFLAGS)
but test1.cpp and test2.cpp works
- If I try to generate test3.o first, and then use the line above, only test3.o is generated, and the error is the same.
- The error is in base_lvl2.o:
Code:
In function 'xxx::xxx::xxx':
base_lvl2.cpp:(.text+0x2f): undefined reference to 'orig_func'
where orig_func is a function that was is test1.c, test1.cpp and test2.cpp directly, but was moved to base_lvl2.cpp.
Does anyone have any idea of why is that happening?
-
At what point do you tell the compiler to link to the C library? When producing base_lvlx.o or the final executable?
-
The final executable. If I try to include the libraries before, the compiler says they where not used.
-
I'm confused how the files are setup. Can you post function declarations and #include statements are in which .h/cpp files?
-
Okay.
First of all, sorry for the big post.
I'm trying to work with CHOLMOD. There is a huge number of functions and definitions here, but all I need to include is cholmod.h, which have extern "C".
All functions that start with cholmod_ are in the library CHOLMOD.
To make it clearer, I have renamed the files to short1.c, short1.cpp, short2.cpp and short3.cpp. They are:
Code:
//short1.c
#include "cholmod.h"
int main (void) {
cholmod_sparse *A ;
cholmod_common c ;
cholmod_start (&c) ; /* start CHOLMOD */
A = cholmod_read_sparse (stdin, &c) ; /* read in a matrix */
cholmod_print_sparse (A, "A", &c) ; /* print the matrix */
cholmod_free_sparse (&A, &c) ;
cholmod_finish (&c) ; /* finish CHOLMOD */
return (0) ;
}
Code:
//short1.cpp
#include "base_matrices.h"
int main (void) {
cholmod_sparse *A ;
cholmod_common c ;
cholmod_start (&c) ; /* start CHOLMOD */
A = cholmod_read_sparse (stdin, &c) ; /* read in a matrix */
cholmod_print_sparse (A, "A", &c) ; /* print the matrix */
cholmod_free_sparse (&A, &c) ;
cholmod_finish (&c) ; /* finish CHOLMOD */
return (0) ;
}
Code:
//short2.cpp
#include "base_matrices.h"
using namespace base_matrices;
int main (void) {
cholmod_sparse *A ;
base_common Common;
A = cholmod_read_sparse (stdin, Common.get_pcm()) ;
cholmod_print_sparse (A, "A", Common.get_pcm()) ;
cholmod_free_sparse (&A, Common.get_pcm()) ;
return (0) ;
}
Code:
//short3.cpp
#include "base_matrices.h"
using namespace base_matrices;
int main (void) {
base_common c;
base_sym_matrix A(c);
A.read_sparse(stdin);
A.print_sparse(string("A"));
return (0) ;
}
Now base_matrices.h, and other needed ones:
Code:
#ifndef base_matrices_h
#define base_matrices_h
#include "base_sym_matrix.h"
#endif
Code:
#ifndef base_sym_matrix_h
#define base_sym_matrix_h
#include "base_common.h"
#include <string>
using std::string;
namespace base_matrices {
class base_sym_matrix {
public:
base_sym_matrix (); //Not defined, because not allowed!
base_sym_matrix (base_common &);
~base_sym_matrix ();
//Needed function
void read_sparse (FILE *);
void print_sparse (string);
cholmod_sparse * get_matrix () { return matrix; };
private:
cholmod_sparse *matrix;
base_common *common;
};
}
#endif
Code:
#ifndef base_common_h
#define base_common_h
#include "cholmod.h"
/* ==============================================
* Class base_common
*
* This class in a wraper for cholmod_common.
* Since cholmod_start(&c) must be the first call to solve
* cholesky by CHOLMOD, then it is in the constructor.
* Also, since cholmod_finish(&c) must be the last call,
* then it is in the destructor.
* Note that base_common will be the first variable created
* because the others will have to point to it.
* ==============================================
*/
namespace base_matrices {
class base_common {
public:
base_common ();
~base_common ();
//Verify which options will need to be set, so that they
//are included here.
cholmod_common *get_pcm () { return common; };
private:
cholmod_common *common;
};
}
#endif
Now, the cpp's:
Code:
#include "base_sym_matrix.h"
namespace base_matrices {
base_sym_matrix::base_sym_matrix (base_common & cm) {
common = &cm;
matrix = 0;
}
base_sym_matrix::~base_sym_matrix () {
cholmod_free_sparse(&matrix, common->get_pcm());
}
void base_sym_matrix::read_sparse (FILE *f) {
matrix = cholmod_read_sparse(f, common->get_pcm());
}
void base_sym_matrix::print_sparse(string name) {
cholmod_print_sparse(matrix, name.c_str(), common->get_pcm());
}
}
Code:
#include "base_common.h"
namespace base_matrices {
base_common::base_common () {
common = new cholmod_common;
cholmod_start(common);
}
base_common::~base_common () {
cholmod_finish(common);
delete common;
}
}
These shortx.c* are short versions of the old files. Now the error is the same ('undefined reference'), but for any cholmod_* function.
Note that the error only happens for short3.cpp, but I compile all 3 cpp files with the same arguments.
Code:
gcc -o shortc -I../Cholesky/CHOLMOD/Include -I../Cholesky/UFconfig -I../Include short1.c ../Cholesky/CHOLMOD/Lib/libcholmod.a ../Cholesky/AMD/Lib/libamd.a ../Cholesky/COLAMD/Lib/libcolamd.a ../Cholesky/CAMD/Lib/libcamd.a ../Cholesky/CCOLAMD/Lib/libccolamd.a ../Cholesky/GotoBLAS2/libgoto2.so -lgfortran -lgfortranbegin ../Cholesky/metis-4.0/libmetis.a -lm -O3 -fexceptions
g++ -o short1 short1.cpp ../Cholesky/CHOLMOD/Lib/libcholmod.a ../Cholesky/AMD/Lib/libamd.a ../Cholesky/COLAMD/Lib/libcolamd.a ../Cholesky/CAMD/Lib/libcamd.a ../Cholesky/CCOLAMD/Lib/libccolamd.a ../Cholesky/GotoBLAS2/libgoto2.so -lgfortran -lgfortranbegin ../Cholesky/metis-4.0/libmetis.a -lm ../Lib/libbasematrices.a -I../Cholesky/CHOLMOD/Include -I../Cholesky/UFconfig -I../Include -O3 -fexceptions -Wall -Werror -Wextra
g++ -o short2 short2.cpp ../Cholesky/CHOLMOD/Lib/libcholmod.a ../Cholesky/AMD/Lib/libamd.a ../Cholesky/COLAMD/Lib/libcolamd.a ../Cholesky/CAMD/Lib/libcamd.a ../Cholesky/CCOLAMD/Lib/libccolamd.a ../Cholesky/GotoBLAS2/libgoto2.so -lgfortran -lgfortranbegin ../Cholesky/metis-4.0/libmetis.a -lm ../Lib/libbasematrices.a -I../Cholesky/CHOLMOD/Include -I../Cholesky/UFconfig -I../Include -O3 -fexceptions -Wall -Werror -Wextra
g++ -o short3 short3.cpp ../Cholesky/CHOLMOD/Lib/libcholmod.a ../Cholesky/AMD/Lib/libamd.a ../Cholesky/COLAMD/Lib/libcolamd.a ../Cholesky/CAMD/Lib/libcamd.a ../Cholesky/CCOLAMD/Lib/libccolamd.a ../Cholesky/GotoBLAS2/libgoto2.so -lgfortran -lgfortranbegin ../Cholesky/metis-4.0/libmetis.a -lm ../Lib/libbasematrices.a -I../Cholesky/CHOLMOD/Include -I../Cholesky/UFconfig -I../Include -O3 -fexceptions -Wall -Werror -Wextra
../Lib/libbasematrices.a(base_common.o): In function `base_matrices::base_common::~base_common()':
base_common.cpp:(.text+0x28): undefined reference to `cholmod_finish'
../Lib/libbasematrices.a(base_common.o): In function `base_matrices::base_common::base_common()':
base_common.cpp:(.text+0x16): undefined reference to `cholmod_start'
../Lib/libbasematrices.a(base_sym_matrix.o): In function `base_matrices::base_sym_matrix::read_sparse(_IO_FILE*)':
base_sym_matrix.cpp:(.text+0x2f): undefined reference to `cholmod_read_sparse'
../Lib/libbasematrices.a(base_sym_matrix.o): In function `base_matrices::base_sym_matrix::~base_sym_matrix()':
base_sym_matrix.cpp:(.text+0x18): undefined reference to `cholmod_free_sparse'
../Lib/libbasematrices.a(base_sym_matrix.o): In function `base_matrices::base_sym_matrix::print_sparse(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
base_sym_matrix.cpp:(.text+0x4e): undefined reference to `cholmod_print_sparse'
-
I've just made the following modification to short3.cpp:
Code:
//short3.cpp modified
#include "base_matrices.h"
using namespace base_matrices;
int main (void) {
cholmod_sparse *B; //Here
base_common Common;
base_sym_matrix A(Common);
B = cholmod_read_sparse(stdin, Common.get_pcm()); //Here
A.read_sparse(stdin);
cholmod_print_sparse(B, "B", Common.get_pcm()); //Here
A.print_sparse(string("A"));
cholmod_free_sparse(&B, Common.get_pcm()); //Here
return (0) ;
}
Which is basically a merge of short2 and short3. It compiled and ran normally. I still don't know why it works. Can anyone help me?
-
Still no solution found, nobody can help with this?
-
Hello all,
I found the problem. My linking was done wrong, because of inverted order of inclusion of libraries. I didn't know that the compiler (g++) reads it from the right to the left.
Thank you