C++ and R: Create a .so or .dll - c++

I have doubt. I know that it is possible to call from a cppfile an Rfunction.
But it is possible to compile that cppfile (that has an R function inside -from a package, for example caret-) into a .soor dll?
If it is possible. How does having a chuck of Rcode inside works. Does the compiled code calls the R interpreter before it compiles or it does not need to?
Thanks in advance

Yes, you can embed R inside of C or C++ application. The API is old, stable, somewhat documented and a little unwieldy. But it can be done.
Or you just use RInside which does everything for you -- and comes with eight (8) different example subdirectories containing dozens of worked and working examples. Here is (the core) of one (which is a little old, we may write it tighter now):
#include <RInside.h> // for the embedded R via RInside
#include <iomanip>
int main(int argc, char *argv[]) {
RInside R(argc, argv); // create an embedded R instance
std::string txt = // load library, run regression, create summary
"suppressMessages(require(stats));"
"swisssum <- summary(lm(Fertility ~ . , data = swiss));"
"print(swisssum)";
R.parseEvalQ(txt); // eval command, no return
// evaluate R expressions, and assign directly into Rcpp types
Rcpp::NumericMatrix M( (SEXP) R.parseEval("swcoef <- coef(swisssum)"));
Rcpp::StringVector cnames( (SEXP) R.parseEval("colnames(swcoef)"));
Rcpp::StringVector rnames( (SEXP) R.parseEval("rownames(swcoef)"));
std::cout << "\n\nAnd now from C++\n\n\t\t\t";
for (int i=0; i<cnames.size(); i++) {
std::cout << std::setw(11) << cnames[i] << "\t";
}
std::cout << std::endl;
for (int i=0; i<rnames.size(); i++) {
std::cout << std::setw(16) << rnames[i] << "\t";
for (int j=0; j<cnames.size(); j++) {
std::cout << std::setw(11) << M(i,j) << "\t";
}
std::cout << std::endl;
}
std::cout << std::endl;
exit(0);
}
Then:
edd#max:~/git/rinside/inst/examples/standard(master)$ make rinside_sample3
ccache g++ -I/usr/share/R/include -I/usr/local/lib/R/site-library/Rcpp/include -I/usr/local/lib/R/site-library/RInside/include -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -g -O3 -Wall -pipe -Wno-unused -pedantic -Wall rinside_sample3.cpp -Wl,--export-dynamic -fopenmp -L/usr/lib/R/lib -lR -lpcre -llzma -lbz2 -lz -lrt -ldl -lm -lblas -llapack -L/usr/local/lib/R/site-library/RInside/lib -lRInside -Wl,-rpath,/usr/local/lib/R/site-library/RInside/lib -o rinside_sample3
edd#max:~/git/rinside/inst/examples/standard(master)$ ./rinside_sample3
Call:
lm(formula = Fertility ~ ., data = swiss)
Residuals:
Min 1Q Median 3Q Max
-15.2743 -5.2617 0.5032 4.1198 15.3213
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 66.91518 10.70604 6.250 1.91e-07 ***
Agriculture -0.17211 0.07030 -2.448 0.01873 *
Examination -0.25801 0.25388 -1.016 0.31546
Education -0.87094 0.18303 -4.758 2.43e-05 ***
Catholic 0.10412 0.03526 2.953 0.00519 **
Infant.Mortality 1.07705 0.38172 2.822 0.00734 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 7.165 on 41 degrees of freedom
Multiple R-squared: 0.7067, Adjusted R-squared: 0.671
F-statistic: 19.76 on 5 and 41 DF, p-value: 5.594e-10
And now from C++
Estimate Std. Error t value Pr(>|t|)
(Intercept) 66.9152 10.706 6.25023 1.90605e-07
Agriculture -0.172114 0.0703039 -2.44814 0.0187272
Examination -0.258008 0.253878 -1.01627 0.315462
Education -0.87094 0.183029 -4.75849 2.4306e-05
Catholic 0.104115 0.0352579 2.95297 0.00519008
Infant.Mortality 1.07705 0.38172 2.82157 0.00733572
edd#max:~/git/rinside/inst/examples/standard(master)$
which shows that
yes we can use R from C++
yes we can have R report the result
yes we can get them back to C++ too
As I said, there are dozens more examples. And no, it doesn't just magically compile R into your executable -- you need R installed and its shared libraries are called.

Related

Sub sequential C calls to R doesn't work

I'm writing a c++ function that takes in a R-call and evaluates it. The function returns as expected whenever I compile with a single call to it.
But when there are sub sequential calls to my function it gets stuck when I run the object file.
How would I re-instantiate the R instance after a single function call?
The method below gets stuck when there are two calls to my function but works fine when I do one call.
int main(int argc, char* argv[]){
double result1 = calculateScalar(input2);
std::cout << "Result 1 " << result1;
double result2 = calculateScalar(input2);
std::cout << "Result 2 " <<result2;
return 0;
}
double calculateScalar(const char* RCALL){
SEXP formula, result;
ParseStatus status;
R_xlen_t len;
int errorStatus;
try {
Rf_initEmbeddedR(0, NULL);
Rf_protect(formula = mkString(RCALL));
Rf_protect(formula = R_ParseVector(formula, 1, &status, R_NilValue));
result = R_tryEval(VECTOR_ELT(formula,0), R_GlobalEnv, &errorStatus);
PROTECT(result);
len = xlength(result);
UNPROTECT(3);
Rf_endEmbeddedR(0);
return (double) getNumericScalar(result);
} catch(std::exception& e){
std::cout << "Standard exception: " << e.what();
}
//Clean up R
Rf_endEmbeddedR(0);
exit(0);
}
Instead of reinventing the wheel, you could just RInside:
edd#brad:~/git/rinside/inst/examples/standard(master)$ make rinside_sample3
ccache g++ -I/usr/share/R/include -I/usr/local/lib/R/site-library/Rcpp/include \
-I/usr/local/lib/R/site-library/RInside/include -g -O3 -Wall -pipe -Wno-unused \
-pedantic -Wall rinside_sample3.cpp -Wl,--export-dynamic -fopenmp\
-L/usr/lib/R/lib -lR -lpcre -llzma -lbz2 -lz -lrt -ldl -lm \
-lblas -llapack -L/usr/local/lib/R/site-library/RInside/lib -lRInside \
-Wl,-rpath,/usr/local/lib/R/site-library/RInside/lib -o rinside_sample3
edd#brad:~/git/rinside/inst/examples/standard(master)$
builds it (automagically using an automated `GNUmakefile) from this simple source file.
Running it yields:
edd#brad:~/git/rinside/inst/examples/standard(master)$ ./rinside_sample3
Call:
lm(formula = Fertility ~ ., data = swiss)
Residuals:
Min 1Q Median 3Q Max
-15.2743 -5.2617 0.5032 4.1198 15.3213
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 66.91518 10.70604 6.250 1.91e-07 ***
Agriculture -0.17211 0.07030 -2.448 0.01873 *
Examination -0.25801 0.25388 -1.016 0.31546
Education -0.87094 0.18303 -4.758 2.43e-05 ***
Catholic 0.10412 0.03526 2.953 0.00519 **
Infant.Mortality 1.07705 0.38172 2.822 0.00734 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 7.165 on 41 degrees of freedom
Multiple R-squared: 0.7067, Adjusted R-squared: 0.671
F-statistic: 19.76 on 5 and 41 DF, p-value: 5.594e-10
And now from C++
Estimate Std. Error t value Pr(>|t|)
(Intercept) 66.9152 10.706 6.25023 1.90605e-07
Agriculture -0.172114 0.0703039 -2.44814 0.0187272
Examination -0.258008 0.253878 -1.01627 0.315462
Education -0.87094 0.183029 -4.75849 2.4306e-05
Catholic 0.104115 0.0352579 2.95297 0.00519008
Infant.Mortality 1.07705 0.38172 2.82157 0.00733572
edd#brad:~/git/rinside/inst/examples/standard(master)$
A few things to note:
I picked this example (among literally dozens of other in the package) as it contains multiple eval...() calls in the C++ code.
It is also cute as it redoes lm() for you.
The actual compilation following make rinside_sample3 will vary from system to system; on mine it reflect some parameters I set in ~/.R/Makevars
I manually narrow the display by four spaces to make it fit.

Undefined reference to (error) in C++ Eclipse but working in Visual Studio 2015

I am trying to integrate AMPL with C/C++ using AMPL-API on Windows-7 in Eclipse Mars 2.0. I created a Makefile project in Eclipse which uses MinGW CC to compile the firstexample code given in their example directory.
firstexample.cpp:
#include <iostream>
#include "ampl/ampl.h"
using namespace std;
int main() {
ampl::AMPL ampl;
// Read the model and data files.
std::string modelDirectory = "models";
ampl.read(modelDirectory + "/diet/diet.mod");
ampl.readData(modelDirectory + "/diet/diet.dat");
// Solve
ampl.solve();
// Get objective entity by AMPL name
ampl::Objective totalcost = ampl.getObjective("total_cost");
// Print it
std::cout << "Objective is: " << totalcost.value() << std::endl;
// Get objective entity by AMPL name
ampl::Objective totalcost = ampl.getObjective("total_cost");
// Print it
std::cout << "Objective is: " << totalcost.value() << std::endl;
// Reassign data - specific instances
ampl::Parameter cost = ampl.getParameter("cost");
cost.setValues(new Tuple[2]{ ampl::Arg("BEEF"), ampl::Arg("HAM")}, new Arg[2]{ 5.01, 4.55 },
2);
std::cout << "Increased costs of beef and ham." << std::endl;
// Resolve and display objective
ampl.solve();
std::cout << "New objective value: " << totalcost.value() << std::endl;
// Reassign data - all instances
ampl::Arg elements[8]{ 3, 5, 5, 6, 1, 2, 5.01, 4.55 };
cost.setValues(elements);
std::cout << "Updated all costs." << std::endl;
// Resolve and display objective
ampl.solve();
std::cout << "New objective value: " << totalcost.value() << std::endl;
// Get the values of the variable Buy in a dataframe object
Variable buy = ampl.getVariable("Buy");
ampl::DataFrame df;
df = buy.getValues();
// Print them
df.print();
ampl::DataFrame df2;
// Get the values of an expression into a DataFrame object
df2 = ampl.getData("{j in FOOD} 100*Buy[j]/Buy[j].ub");
// Print them
df2.print();
}
Following is my Makefile:
CC = g++
CFLAGS = -O2 -g -Wall -fmessage-length=0
INCLUDES = -I "C:\\Local\\AMPL\\AMPL32\\amplapi32\\include"
OBJS = AMPL.o
LFLAGS = -L "C:\\Local\\AMPL\\AMPL32\\amplapi32\\lib"
LIBS = -lampl1.2.2
TARGET = AMPL.exe
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(TARGET) $(OBJS) $(LFLAGS) $(LIBS)
AMPL.o: AMPL.cpp
$(CC) $(CFLAGS) $(INCLUDES) -c AMPL.cpp
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
I have added path of required dll files (libampl1.2.2.dll) to the environment variables. I am able to compile and execute code on Visual Studio 2015 with two minor changes:
Without using Makefile (It is a Win32 Console Application)
Adding #include "stdafx.h" in firstexample.cc
However when I execute the same code in Eclipse, it gives me following error:
src\AMPLTesting.o: In function `ZN4ampl8internal11deleteTupleERNS0_5TupleE':
C:/Local/AMPL/AMPL32/amplapi32/include/ampl/ep/tuple_ep.h:24: undefined reference to `_imp___ZN4ampl8internal24AMPL_Variant_DeleteArrayEPKNS0_7VariantE'
src\AMPLTesting.o: In function `ZN4ampl8internal12TupleBuilderC1Ej':
C:/Local/AMPL/AMPL32/amplapi32/include/ampl/ep/tuple_ep.h:35: undefined reference to `_imp___ZN4ampl8internal24AMPL_Variant_CreateArrayEjPNS0_16ErrorInformationE'
collect2.exe: error: ld returned 1 exit status
I am not sure what is the problem? Am I missing some command line option in the Makefile or not adding any specific library? Please help me with this.
The beta version of the C++ API only supports MSVC on Windows at the moment. Support for other compilers will be added in future releases.

C++ / R: RInside in Windows 7 machine

This question is related to: C++ and R: Create a .so or .dll plus i have read the questions and replies of these posts:
Compiling RInside programs on Windows
Problem with compiling RInside examples under Windows
I try to run the code provided as an example in the answer provided
#include <RInside.h> // for the embedded R via RInside
#include <iomanip>
int main(int argc, char *argv[]) {
RInside R(argc, argv); // create an embedded R instance
std::string txt = // load library, run regression, create summary
"suppressMessages(require(stats));"
"swisssum <- summary(lm(Fertility ~ . , data = swiss));"
"print(swisssum)";
R.parseEvalQ(txt); // eval command, no return
// evaluate R expressions, and assign directly into Rcpp types
Rcpp::NumericMatrix M( (SEXP) R.parseEval("swcoef <- coef(swisssum)"));
Rcpp::StringVector cnames( (SEXP) R.parseEval("colnames(swcoef)"));
Rcpp::StringVector rnames( (SEXP) R.parseEval("rownames(swcoef)"));
std::cout << "\n\nAnd now from C++\n\n\t\t\t";
for (int i=0; i<cnames.size(); i++) {
std::cout << std::setw(11) << cnames[i] << "\t";
}
std::cout << std::endl;
for (int i=0; i<rnames.size(); i++) {
std::cout << std::setw(16) << rnames[i] << "\t";
for (int j=0; j<cnames.size(); j++) {
std::cout << std::setw(11) << M(i,j) << "\t";
}
std::cout << std::endl;
}
std::cout << std::endl;
exit(0);
}
The error in the CMD is the following
C:\Users\DON\Desktop>R CMD SHLIB final.cpp
g++ -m64 -I"C:/R/R-3.2.4/include" -DNDEBUG -I"d:/RCompile/r-compiling/local/
local323/include" -O2 -Wall -mtune=core2 -c final.cpp -o final.o
final.cpp:1:74: fatal error: RInside.h: No such file or directory
compilation terminated.
make: *** [final.o] Error 1
Warning message:
comando ejecutado 'make -f "C:/R/R-3.2.4/etc/x64/Makeconf" -f "C:/R/R-3.2.4/shar
e/make/winshlib.mk" SHLIB_LDFLAGS='$(SHLIB_CXXLDFLAGS)' SHLIB_LD='$(SHLIB_CXXLD)
' SHLIB="final.dll" WIN=64 TCLBIN=64 OBJECTS="final.o"' tiene estatus 2
Clearly it cant find the RInside.h header. I have the R installed in a folder without spaces. The PATH in global variables have: C:\R\R-3.2.4\bin; C:\Rtools\bin;C:\Rtools\gcc-4.6.3\bin
I understand that in the CMD i cant introduce comands like
$ export PKG_LIBS=‘Rscript -e "Rcpp:::LdFlags()"‘ # if Rcpp older than 0.11.0
$ export PKG_CXXFLAGS=‘Rscript -e "Rcpp:::CxxFlags()"‘
Which first defines and exports two relevant environment variables which R CMD SHLIB then relies on (as put in the FAQ file)
Any advice on this? I need to do a Makefile for each cpp file that i want to compile?
The error is in your approach. You did
R CMD SHLIB final.cpp
which is nowhere given as the correct approach for working with RInside.
Because we need to tell R about headers and libraries for several components, you are supposed to
cd inst/examples/standard
make # build all
or
make rinside_sample3 # build just this
or, if you're on that OS,
make -f Makefile.win # all
or
make -f Makefile.win rinside_sample3
as the Makefile tells R where do find this. That also answers your second question: One Makefile per directory will do. And look at the Makefile: it sets several include directives; your approach only dealt with Rcpp so of course you get an error about RInside.h not found.
I think you keep asking the same question over and over.

"Bad" GCC optimization performance

I am trying to understand why using -O2 -march=native with GCC gives a slower code than without using them.
Note that I am using MinGW (GCC 4.7.1) under Windows 7.
Here is my code :
struct.hpp :
#ifndef STRUCT_HPP
#define STRUCT_HPP
#include <iostream>
class Figure
{
public:
Figure(char *pName);
virtual ~Figure();
char *GetName();
double GetArea_mm2(int factor);
private:
char name[64];
virtual double GetAreaEx_mm2() = 0;
};
class Disk : public Figure
{
public:
Disk(char *pName, double radius_mm);
~Disk();
private:
double radius_mm;
virtual double GetAreaEx_mm2();
};
class Square : public Figure
{
public:
Square(char *pName, double side_mm);
~Square();
private:
double side_mm;
virtual double GetAreaEx_mm2();
};
#endif
struct.cpp :
#include <cstdio>
#include "struct.hpp"
Figure::Figure(char *pName)
{
sprintf(name, pName);
}
Figure::~Figure()
{
}
char *Figure::GetName()
{
return name;
}
double Figure::GetArea_mm2(int factor)
{
return (double)factor*GetAreaEx_mm2();
}
Disk::Disk(char *pName, double radius_mm_) :
Figure(pName), radius_mm(radius_mm_)
{
}
Disk::~Disk()
{
}
double Disk::GetAreaEx_mm2()
{
return 3.1415926*radius_mm*radius_mm;
}
Square::Square(char *pName, double side_mm_) :
Figure(pName), side_mm(side_mm_)
{
}
Square::~Square()
{
}
double Square::GetAreaEx_mm2()
{
return side_mm*side_mm;
}
main.cpp
#include <iostream>
#include <cstdio>
#include "struct.hpp"
double Do(int n)
{
double sum_mm2 = 0.0;
const int figuresCount = 10000;
Figure **pFigures = new Figure*[figuresCount];
for (int i = 0; i < figuresCount; ++i)
{
if (i % 2)
pFigures[i] = new Disk((char *)"-Disque", i);
else
pFigures[i] = new Square((char *)"-Carré", i);
}
for (int a = 0; a < n; ++a)
{
for (int i = 0; i < figuresCount; ++i)
{
sum_mm2 += pFigures[i]->GetArea_mm2(i);
sum_mm2 += (double)(pFigures[i]->GetName()[0] - '-');
}
}
for (int i = 0; i < figuresCount; ++i)
delete pFigures[i];
delete[] pFigures;
return sum_mm2;
}
int main()
{
double a = 0;
StartChrono(); // home made lib, working fine
a = Do(10000);
double elapsedTime_ms = StopChrono();
std::cout << "Elapsed time : " << elapsedTime_ms << " ms" << std::endl;
return (int)a % 2; // To force the optimizer to keep the Do() call
}
I compile this code twice :
1 : Without optimization
mingw32-g++.exe -Wall -fexceptions -std=c++11 -c main.cpp -o main.o
mingw32-g++.exe -Wall -fexceptions -std=c++11 -c struct.cpp -o struct.o
mingw32-g++.exe -o program.exe main.o struct.o -s
2 : With -O2 optimization
mingw32-g++.exe -Wall -fexceptions -O2 -march=native -std=c++11 -c main.cpp -o main.o
mingw32-g++.exe -Wall -fexceptions -O2 -march=native -std=c++11 -c struct.cpp -o struct.o
mingw32-g++.exe -o program.exe main.o struct.o -s
1 : Execution time :
1196 ms (1269 ms with Visual Studio 2013)
2 : Execution time :
1569 ms (403 ms with Visual Studio 2013) !!!!!!!!!!!!!
Using -O3 instead of -O2 does not improve the results.
I was, and I still am, pretty convinced that GCC and Visual Studio are equivalents, so I don't understand this huge difference.
Plus, I don't understand why the optimized version is slower than the non-optimized version with GCC.
Do I miss something here ?
(Note that I had the same problem with genuine GCC 4.8.2 on Ubuntu)
Thanks for your help
Considering that I don't see the assembly code, I'm going to speculate the following :
The allocation loop can be optimized (by the compiler) by removing the if clause and causing the following :
for (int i=0;i <10000 ; i+=2)
{
pFigures[i] = new Square(...);
}
for (int i=1;i <10000 ; i +=2)
{
pFigures[i] = new Disk(...);
}
Considering that the end condition is a multiple of 4 , it can be even more "efficient"
for (int i=0;i < 10000 ;i+=2*4)
{
pFigures[i] = ...
pFigures[i+2] = ...
pFigures[i+4] = ...
pFigures[i+6] = ...
}
Memory wise this will make Disks to be allocated 4 by 4 an Squares 4 by 4 .
Now, this means they will be found in the memory next to each other.
Next, you are going to iterate the vector 10000 times in a normal order (by normal i mean index after index).
Think about the places where these shapes are allocated in memory.You will end up having 4 times more cache misses (think about the border example, when 4 disks and 4 squares are found in different pages, you will switch between the pages 8 times... in a normal case scenario you would switch between the pages only once).
This sort of optimization (if done by the compiler, and in your particular code) optimizes the time for Allocation , but not the time of access (which in your example is the biggest load).
Test this by removing the i%2 and see what results you get.
Again this is pure speculation, and it assumes that the reason for lower performance was a loop optimization.
I suspect that you've got an issue unique to the combination of mingw/gcc/glibc on Windows because your code performs faster with optimizations on Linux where gcc is altogether more 'at home'.
On a fairly pedestrian Linux VM using gcc 4.8.2:
$ g++ main.cpp struct.cpp
$ time a.out
real 0m2.981s
user 0m2.876s
sys 0m0.079s
$ g++ -O2 main.cpp struct.cpp
$ time a.out
real 0m1.629s
user 0m1.523s
sys 0m0.041s
...and if you really take the blinkers off the optimizer by deleting struct.cpp and moving the implementation all inline:
$ time a.out
real 0m0.550s
user 0m0.543s
sys 0m0.000s

Compiling Trilino

I'm trying to compile a simple test program using the Trilino package but something is wrong. The install of Trilino have went fine as far as I know but there must be something wrong with the linking or something. Below is my makefile:
include /home/jacob/Trilinos/trilinos-build/Makefile.export.Trilinos
CXX=$(Trilinos_CXX_COMPILER)
CC=$(Trilinos_C_COMPILER)
FORT=/usr/bin/gfortran
CXX_FLAGS=$(Trilinos_CXX_COMPILER_FLAGS) $(USER_CXX_FLAGS)
C_FLAGS=$(Trilinos_C_COMPILER_FLAGS) $(USERC_FLAGS)
FORT_FLAGS=$(Trilinos_Fortran_COMPILER_FLAGS) $(USER_FORT_FLAGS)
INCLUDE_DIRS=$(Trilinos_INCLUDE_DIRS) $(Trilinos_TPL_INCLUDE_DIRS)
LIBRARY_DIRS=$(Trilinos_LIBRARY_DIRS) $(Trilinos_TPL_LIBRARY_DIRS)
LIBRARIES=$(Trilinos_LIBRARIES) $(Trilinos_TPL_LIBRARIES)
LINK_FLAGS=$(Trilinos_EXTRA_LD_FLAGS)
DEFINES=-DMYAPP_EPETRA
default: print_info vector.x
vector.x: libmyappLib.a
$(CXX) $(CXX_FLAGS) libMyappLib.a -o vector.x $(LINK_FLAGS) $(INCLUDE_DIRS) $(DEFINES) $(LIBRARY_DIRS) $(LIBRARIES)
libmyappLib.a: es.o
$(Trilinos_AR) cr libMyappLib.a es.o
es.o:
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_DIRS) $(DEFINES) es.cpp
And here is the program:
#include "Epetra_SerialComm.h"
#include "Epetra_Map.h"
#include "Epetra_Vector.h"
#include "Epetra_Version.h"
int main(int argc, char *argv[])
{
std::cout << Epetra_Version() << std::endl << std::endl;
Epetra_SerialComm Comm;
int NumElements = 1000;
Epetra_Map Map(NumElements, 0, Comm);
Epetra_Vector x(Map);
Epetra_Vector b(Map);
b.Random();
x.Update(2.0, b, 0.0); // x = 2*b
double bnorm, xnorm;
x.Norm2(&xnorm);
b.Norm2(&bnorm);
std::cout << "2 norm of x = " << xnorm << std::endl
<< "2 norm of b = " << bnorm << std::endl;
return 0;
}
However, when running make it just gives back:
es.cpp:(.text.startup+0x91): undefined reference to Epetra_SerialComm::Epetra_SerialComm()
es.cpp:(.text.startup+0xa7): undefined reference to `Epetra_Map::Epetra_Map(int,int, Epetra_Comm const&)'
es.cpp:(.text.startup+0xbb): undefined reference to `Epetra_Vector::Epetra_Vector(Epetra_BlockMap const&, bool)'
.
.
.
collect2: error: ld returned 1 exit status
make: *** [vector.x] Fel 1
For every piece of code inside main, so it seems like it cannot find the Epetra package even though itś not complaining about the includes. Does anyone have a clue of what might be the problem? I'm fairly new to C++/C and handling the Trilino package is rather complicated so any tip is highly appreciated.