0

I have a very simple piece of C++ code justread.cc reading numbers from a file. After the command

ludi@ludi-M17xR4:~/Desktop/tests$ g++ -Wall -pedantic -o justread.x justread.cc && ./justread.x

it compiles without any errors or warnings. This is the code:

#include <fstream>
#include <vector>


int read_covariance ()
  {
    std::vector<double> data;
    double tmp;

    std::ifstream fin("peano_covariance.data");

    while(fin >> tmp)
    {
        data.push_back(tmp);
    }

    return 0;
}

int main()
{
read_covariance();
return 0;
}

I wish to use this within an other working code called sylapack.cc. I can not post sylapack.cc due to copyright reasons, but it is taken from the documentation here

https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dsyev_ex.c.htm

without any modifications except removing the spurious lines

< Table Of Contents Intel® Math Kernel Library LAPACK Examples

at the top of the webpage.

I can compile sylapack.cc as C code without errors or warnings:

ludi@ludi-M17xR4:~/Desktop/tests$ gcc -Ddsyev=dsyev_ -o sylapack sylapack.c -L/usr/local/lib -llapack -lblas && ./sylapack
 DSYEV Example Program Results

 Eigenvalues
 -11.07  -6.23   0.86   8.87  16.09

 Eigenvectors (stored columnwise)
  -0.30  -0.61   0.40  -0.37   0.49
  -0.51  -0.29  -0.41  -0.36  -0.61
  -0.08  -0.38  -0.66   0.50   0.40
  -0.00  -0.45   0.46   0.62  -0.46
  -0.80   0.45   0.17   0.31   0.16
ludi@ludi-M17xR4:~/Desktop/tests$ 

I wish to integrate the C++ function read_covariance into sylapack.cc. To that end I have to compile sylapack.cc with g++. This gives me errors.

ludi@ludi-M17xR4:~/Desktop/tests$ g++ -Ddsyev=dsyev_ -o sylapack sylapack.c -L/usr/local/lib -llapack -lblas && ./sylapack
sylapack.c: In function ‘int main()’:
sylapack.c:89:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
         dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info );
                                                                          ^
sylapack.c:89:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
sylapack.c:93:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
         dsyev( "Vectors", "Upper", &n, a, &lda, w, work, &lwork, &info );
                                                                        ^
sylapack.c:93:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
sylapack.c:100:49: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
         print_matrix( "Eigenvalues", 1, n, w, 1 );
                                                 ^
sylapack.c:102:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
         print_matrix( "Eigenvectors (stored columnwise)", n, n, a, lda );
                                                                        ^
/tmp/ccz2hTYK.o: In function `main':
sylapack.c:(.text+0xa3): undefined reference to `dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*)'
sylapack.c:(.text+0x12a): undefined reference to `dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*)'
collect2: error: ld returned 1 exit status
ludi@ludi-M17xR4:~/Desktop/tests$ 
Ludi
  • 451
  • 4
  • 17

1 Answers1

1

You want to have "C" linkage when mixing C++ and C. See the explanation there In C++ source, what is the effect of extern "C"?

Indeed modifying the lines

/* DSYEV prototype */
extern void dsyev( char* jobz, char* uplo, int* n, double* a, int* lda,
                double* w, double* work, int* lwork, int* info );
/* Auxiliary routines prototypes */
extern void print_matrix( char* desc, int m, int n, double* a, int lda );

to these:

/* DSYEV prototype */
extern "C"{
void dsyev( char* jobz, char* uplo, int* n, double* a, int* lda,
                double* w, double* work, int* lwork, int* info );
}
/* Auxiliary routines prototypes */
extern "C"{ 
void print_matrix( char* desc, int m, int n, double* a, int lda );
}

removed the errors.

Community
  • 1
  • 1
bendervader
  • 2,619
  • 2
  • 19
  • 22
  • Thank you! This removed the errors and left only the warnings. I am a n00b. Can you explain how the "extern void function" that was already present is different from extern "C" {void function}? – Ludi Jun 06 '15 at 20:18
  • Are you asking about deprecated conversion from string constant to ‘char*’? With newer c++ compilers a variable in quotes "like this" defaults to type std::string. The C code expects const char* so the compiler does an implicit conversion. To avoid this you can do std::string("my string").c_str(), or cast it explicitly (const char*)"my string" . The warning is not a big deal though. I don't understand the "how the "extern void function" that was already present is different from extern "C" {void function}" – bendervader Jun 06 '15 at 20:24
  • 1
    NOTE: "print_matrix" needs to be an extern, iff it is being called in a pre-compiled C library. If this your own code, it does not require extern linkage. Also, I'd assume print_matrix does not modify the matrix. Hence, the pointer to the matrix should be const, i.e. "const double* a" – bendervader Jun 06 '15 at 20:27
  • @bendervader You are wrong. The type of a string literal like `"hello"` is always `const char[]`, even for recent compilers. See http://en.cppreference.com/w/cpp/language/string_literal But a `const char[]`, pointing to a constant string, should not be addressed with a pointer to a non-const array of char (`char*`). You are mixing up with standard user-defined literals, like `"hello"s`, in C++14: http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s – lrineau Jun 03 '16 at 10:22