How to add an external library in c++ using Cygwin - c++

I've already wasted time trying to figure this out but no luck so far...I've tried looking through StackOverflow for the same problem but mostly it's related to the IDE people are using, such as VS or Eclipse.
I was doing some examples from the Stanford Reader for their C++ course but the code won't work right. I'm trying to figure out how to use external libraries but something keeps going wrong. I'm probably not using the right command but then I don't know which command to use.
I'm using Cygwin and it's terminal to do the c++ exercises. I have all the files in the same folder. I am using windows 7 but that shouldn't be the biggest problem though.
As an example this error shows well what I get when writing g++ Craps.cpp:
$ g++ Craps.cpp
/tmp/ccdTdi0t.o:Craps.cpp:(.text+0x1cf): undefined reference to `randomInteger(int, int)'
/tmp/ccdTdi0t.o:Craps.cpp:(.text+0x1e6): undefined reference to `randomInteger(int, int)'
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../i686-pc-cygwin/bin/ld: /tmp/ccdTdi0t.o: bad
reloc address 0x0 in section `.ctors'
collect2: ld returned 1 exit status
The example I was running this time is just one of the ones with external libraries which gives me the same kind of error if I wrong the other. It won't find the library.
This is my main also called Craps.cpp:
#include <iostream>
#include "random.h"
using namespace std;
bool tryToMakePoint(int point);
int rollTwoDice();
int main() {
cout << "This program plays a game of craps." << endl;
int point = rollTwoDice();
switch (point) {
case 7: case 11:
cout << "That's a natural. You win." << endl;
break;
case 2: case 3: case 12:
cout << "That's craps. You lose" << endl;
break;
default:
cout << "Your point is " << point << "." << endl;
if (tryToMakePoint(point)) {
cout << "You made your point. You win." << endl;
} else {
cout << "You rolled a seven. You lose." << endl;
}
}
return 0;
}
bool tryToMakePoint(int point) {
while (true) {
int total = rollTwoDice();
if (total == point) return true;
if (total == 7) return false;
}
}
int rollTwoDice() {
cout << "Rolling the dice . . . " << endl;
int d1 = randomInteger(1, 6);
int d2 = randomInteger(1, 6);
int total = d1 + d2;
cout << "You rolled " << d1 << " and " << d2
<< " - that's " << total << endl;
return total;
}
My random.cpp:
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "random.h"
using namespace std;
void initRandomSeed();
int randomInteger(int low, int high) {
initRandomSeed();
double d = rand() / (double(RAND_MAX) + 1);
double s = d * (double(high) - low + 1);
return int(floor(low + s ));
}
double randomReal(double low, double high) {
initRandomSeed();
double d = rand() / (double(RAND_MAX) + 1);
double s = d * (high - low);
return low + s;
}
bool randomChance(double p) {
initRandomSeed();
return randomReal(0, 1) < p;
}
void setRandomSeed(int seed) {
initRandomSeed();
srand(seed);
}
void initRandomSeed() {
static bool initialized = false;
if (!initialized) {
srand(int(time(NULL)));
initialized = true;
}
}
and lastly my random.h:
#ifndef _random_h
#define _random_h
int randomInteger(int low, int high);
double randomReal(double low, double high);
bool randomChance(double p);
void setRandomSeed(int seed);
#endif
I hope someone can help me. If it's the Cygwin command that's wrong it would be great if I could see what I should write.
Edit:
Just found out that I couldn't even write down the examples in the book right. Fixed now and should be without mistakes...I dearly hope so. Sorry about that.

Shortly, you should add random.cpp (or, if you already compiled it, an object file or a library where its compiled code resides) into your command line:
g++ Craps.cpp random.cpp
The problem you face is that the command line says the code in Craps.cpp should be compiled and then linked into an executable. While it's sufficient to have forward declarations of external functions to compile the file, you should provide the code of these functions to the linker for it to be able to create an executable.
As for libraries, you usually specify ones that you need to use with -l option to GCC. And you might need to specify (with -L) the path where to take libraries from, even if they all are in the current directory. E.g. provided that you have a library called librandom.a or librandom.so in the current directory:
g++ Craps.cpp -L. -l random
For external libraries, other directories may need to be specified so that the linker knows where to find the libraries it needs.

Other answer has the simple command to compile this, but here's a very rough and simple Makefile example, to get you started down that road. Create a file named Makefile with these contents, where <tab> must be an actual tab character, not some number of spaces:
Craps.exe : Craps.o random.o
<tab>g++ -o $# $^
Craps.o random.o : random.h
Then just run
make Craps.exe
(possibly gmake or mingw32-make instead of plain make).
Now Make has some magic built in about file types, so when it sees Craps.exe needs those two .o files, it'll start looking for files it could make them from, and it finds .cpp files, and knows how to compile them into .o files. Now it doesn't implicitly know how make .exe out of .o files, so that's why we have the 2nd line. There $# means the target of the rule (Craps.exe here), while $^ means all the files listed after the :.
The Craps.o random.o:random.h rule means, that if random.h is changed, Craps.o and random.o needs to be re-created again (these .h file dependencies can be generated automatically, but as long as you have just a few files, writing them by hand is ok).
If you need to add more source files, just add them with the .o suffix to the first line, and make will include them in the compilation. Also note how make will only compile changed files... Then you will need to add .h file dependencies when you get more .h files.

Related

Unused variable warning even when explicitly using it inside IF statement

I am trying to create (using C++17) a simple debug header that only executes some lines of code if the flag LOGGER_DEBUG_MODE is enabled. This is how my header is defined (I also tried using { x; } instead of x but the warning persists):
debug.h
#ifndef _HDEBUG
#define _HDEBUG
static bool LOGGER_DEBUG_MODE = true;
#define R_DEBUG(x) if(LOGGER_DEBUG_MODE == true) x
#endif
I included debug.h and at some point of my code I call the macro function R_DEBUG to print some values:
logger_adc.cpp
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
R_DEBUG(std::cout << "Eval Result: " << result << std::endl);
return result;
}
I expected everything to work properly but when I run the makefile I got this warning:
inc/debug.h:5:14: warning: 'LOGGER_DEBUG_MODE' defined but not used [-Wunused-variable]
static bool LOGGER_DEBUG_MODE = true;
I thought that my definition was messed up but after checking the temporary files created by g++, it appears that the preprocessor did everything as I expected:
logger_adc.ii
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
if(LOGGER_DEBUG_MODE == true) std::cout << "Eval Result: " << result << std::endl;
return result;
}
Why do I get the warning message even when the variable LOGGER_DEBUG_MODE is clearly being used inside the if statement? Did I mess up something obvious that I'm not picking up? My compile flags for the object files (where the warning occurs) are g++ -Wall -Wextra -O1 -g -std=c++17 -save-temps=obj -Iinc -I/usr/local/include -c plus pkg-config --cflags --libs libmodbus
If needed, this is my main function:
main.cpp
#include "logger_adc.h"
int main()
{
anlg_device_t test (ADC_CHIP_1, 1, 18, 1, 1, true);
test.set_formula("2*x","x", test.get_voltage_ptr());
std::cout << "Test Voltage: " << test.get_voltage() << std::endl << "Test Relative: " << test.get_relative() << std::endl;
std::cout << "Test Formula (2*x): " << test.eval_formula() << std::endl;
return 0;
}
Thanks in advance!
You have a header that defines a static bool LOGGER_DEBUG_MODE =true;. If you include that header in multiple C++ files then each file will gets its own copy of that bool.
In your main.cpp you aren't using R_DEBUG so the copy of that bool (which presumably comes from including logger_adc.h ) is indeed unused in that file.
Possible solutions are:
You should make it so you only have a single copy of that bool (declare it in the header with extern and define it in a single C++ file.
Use build defines instead of runtime checks
etc

Is there anything redundant that I have done or am I, a C++ newbie, missing out anything here?

CODE:
#include <iostream>
#include <cmath>
using namespace std;
//To import packages we use #include.
int integers() {
//Math operations passed onto cout will automatically calculate itself.
inum ++;
dnum --;
cout << inum << endl;
//For example, pow()
cout << pow(2, 6);
//++ function makes variables increment by 1, -- also does that, reversed.
}
ERROR:
[Running] cd "c:\Users\Administrator\Desktop\C++Workplace\C++Basics\" && g++ NumberUses.cpp -o
NumberUses && "c:\Users\Administrator\Desktop\C++Workplace\C++Basics\"NumberUses
C:/TDM-GCC-32/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:/TDM-GCC-
32/bin/../lib/gcc/mingw32/9.2.0/../../../libmingw32.a(main.o):(.text.startup+0xc0): undefined reference
to `WinMain#16'
collect2.exe: error: ld returned 1 exit status
[Done] exited with code=1 in 0.747 seconds
Is there anything I'm missing out with all those functions? Essentially I'm a newbie and is there any old version confusions between syntax, formatting, etc...?
Your code missing main function, which starts the program;
and
You must declare you variables before use them;
int main() {
int inum = 0, dnum = 0;
inum++;
dnum--;
std::cout << inum << std::endl;
std::cout << std::pow( 2, 6 );
}

How to use vectors to find mean and standard deviation

This is the assignment:
Write two functions that calculate the mean and standard deviation.
Your functions shall implement the following prototypes:
double mean(vector<double>x);
double sd(vector<double>x);
b. Place these functions in a file named “statfun.cpp”.
c. Place their function definitions in a file named “statfun.h”.
Write a main() function in a file named “lab1.cpp”.
Prompt the user to input 10 floating-point values and store them in a vector v.
Print vector v on a single line with each element separated by a space.
Call your functions mean(v) and sd(v) ...
I know how to code the formula for mean, but I'm not sure how to code the formula for standard deviation using vectors. I'm even less sure of how to do this with different files involved. I'm fully aware my code is garbage, but there are so many things I'm not sure of, I don't know what to tackle first.
Edit: Updated the code
//statfun.h
#include <iostream>
#include <vector>
#ifndef STATFUN_H
#define STATFUN_H
using namespace std;
double mean(vector<double> v);
double sd(vector<double> v);
#endif
//statfun.cpp
#include <iostream>
#include <cmath>
#include <vector>
#include "statfun.h"
#ifndef STATFUN_CPP
#define STATFUN_CPP
using namespace std;
double mean(const vector<double> v) {
double result;
double sumVal = 0.0; //Calculating sum of all values
for (int i = 0; i < v.size(); ++i) {
sumVal = sumVal + v.at(i);
}
result = sumVal / v.size(); //Calculating mean
return result;
}
double sd(const vector<double> v) {
double total = 0;
for (int i = 0; i < 10; ++i) { //Calcuating standard deviation
double mean_value = mean(v);
int length = v.size()
total = total + (val - mean_value)*(val - mean_value);
}
return sqrt(total / length);
}
#endif
//lab1.cpp
#include "statfun.cpp"
#include <iomanip>
using namespace std;
vector<double> v;
int main() {
cout << "Enter 10 numbers: " << endl;
float userInput = 0;
for (int i = 0; i < 10; ++i) {
cin >> userInput;
v.push_back(userInput);
}
for (int i = 0; i < 10; ++i) {
cout << v.at(i) << " ";
}
cout << endl;
cout.precision(3);
cout << mean(v) << " " << sd(v) << endl;
cout.precision(5);
cout << scientific << mean(v) << " " << sd(v) << endl;
return 0;
}
You made many mistakes and your code has much to improve.
Let me show you me by me.
The header
Since one file can include header multiple times, to prevent any side effect of this, an include guard is required for each header file.
// statfun.h
#ifndef __statfun_H__
# define __statfun_H__
# include <vector>
double mean(const std::vector<double>&);
double sd(const std::vector<double>&);
#endif
BTW, a function declaration can abbreviate the arguments' name.
Reference
The second mistake you made is that you didn't use reference. In c++, an object is by default passed by value.
Note: This is just like R, except it doesn't have language level copy-on-write semantics, but user-defined class can implement this, classes defined in std namespace can also implement this.
So in order to prevent costy copy, reference is made.
double mean(const std::vector<double>&);
Here I used const left-value reference (const &), since mean will not modify the vector passed in.
Function blocks.
In c++, a function is defined as below:
return_value func_name(type1 arg1 /* , type2 arg2, ... */)
{
// The function body goes here:
}
So
// statfun.cpp
// c++11
#include "statfun.h"
#include <cmath>
double mean(const std::vector<double> &v)
{
double sum = 0;
for (auto &each: v)
sum += each;
return sum / v.size();
}
double sd(const std::vector<double> &v)
{
double square_sum_of_difference = 0;
double mean_var = mean(v);
auto len = v.size();
double tmp;
for (auto &each: v) {
tmp = each - mean_var;
square_sum_of_difference += tmp * tmp;
}
return std::sqrt(square_sum_of_difference / (len - 1));
}
Compile-time variable type deduction
As you might have noticed in the code above, I used auto len = v.size(), which is a c++11 language feature -- auto.
Since c++11, c++ can deduce the return type of function calls at compile-time. So instead of define variable like typename std::vector<double>::size_type len = v.size(), we now have auto len = v.size().
range-for loop
If you have learnt python, then you must know range-for. Since c++11, c++ can also do this:
for (auto &each: v) {
// Loop body
}
where v can be std::vector or any other container in c++.
IO error check
Last but not least, you didn't check if any of these IO you performed on std::cout or std::cin succeeds or not!
Using std::cout or std::cin, you have to check stream state by std::cout.fail() every time after you performed an IO, or use the following code:
std::cout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
To make std::cout and std::cin throws when an IO fails.
I personally like to not handle this error and let the exception terminates the program, since there is nothing you can do to cleanup and resume the control flow of the program.
Below is the last piece of code:
// lab1.cpp
// c++11
#include "statfun.h"
#include <iostream>
auto get_use_input() -> std::vector<double>
{
std::vector<double> v;
v.reserve(10);
double userInput;
for (int i = 0; i != 10; ++i) {
std::cout << "Please enter the " << i + 1 << " number: ";
std::cin >> userInput;
std::cout << std::endl;
v.push_back(userInput);
}
return v;
}
void print_vec(const std::vector<double> &v)
{
std::cout << "Vector: ";
for (auto &each: v)
std::cout << each << " ";
std::cout << std::endl;
}
int main() {
// Configure std::cout and std::cin to throw if io fails.
std::cout.exceptions(std::ios_base::failbit | std::ios_base::badbit);
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
/*
* With "-O3" or [c++17, copy elision](https://en.cppreference.com/w/cpp/language/copy_elision),
* the cost of initializing an object using the return value of anther function is nearly zero.
*/
std::vector<double> v = get_use_input();
print_vec(v);
std::cout.precision(3);
std::cout << "mean: " << mean(v) << " sd: " << sd(v) << std::endl;
std::cout.precision(5);
std::cout <<std::scientific << "mean: " << mean(v) << " sd: " << sd(v) << std::endl;
return 0;
}
To build this program, you must have a c++ compiler that supports c++11 and pass -std=c++11 to the compiler.
PS: You can also use -std=c++14 or -std=c++17.
A simple Makefile to build the program:
cxx = ${CXX}
# The flags
CPPFLAGS := -std=c++11
# The two line below is the flags I used for clang++-8
# CPPFLAGS := -std=c++17 -Ofast -pipe -flto
# LDFLAGS := -flto -pipe -Wl,--icf=all,-O2,--as-needed,--strip-all,--plugin-opt=O3
lab1: lab1.o statfun.o
$(CXX) $(LDFLAGS) $^ -o $#
statfun.o: statfun.h
lab1.o: statfun.h
.PHONY: clean
rm -f lab1.o statfun.o lab
I believe your first issue is in understanding the file structure of your stats assignment. Tackle this first. Understanding headers. More on headers and function calls from other files.
The .cpp files will contain implementation of logic, the .h files are headers that should declare definitions of objects and functions. When you include files at the top of your code, generally think of this as having all the code from that file above the current file.
Example:
statfun.h
double mean(vector<double> v);
// other **declaration** stuff....
lab1.cpp at the top of the file
#include "statfun.h" // equivalent to copy/pasting 'double mean(vector<double> v); and other declarations' into your lab1.cpp
// This is to help with cleanliness of your file structure.
// You'll thank yourself when projects become bigger.
Note: lab1.cpp includes statfun.cpp which includes statfun.h; implicitly, lab1.cpp includes statfun.h which means you don't have to include statfun.h in lab1, although typically the header is included, not the cpp file. You must avoid circular dependencies which you do with the ifndef.
b. statfun.cpp should be the place where you code all of your logic for the mean and standard deviation.
example:
statfun.cpp
double mean(vector<double> v) {
// Your mean calculation logic here.
return mean;
}
double sd(vector<double> x) {
// Your standard deviation calculation logic here.
return sd;
}
c.
So you have lab1.cpp which will be compiled to produce some runnable binary. As the entry point of your program, it should include an int main() function. This main function needs to ask for user input (search the webs for how to take std input).
Store the standard input as a vector (this is still in your main function).
Use cout to print to standard out. 'cout << name_of_variable_with_vector_input_from_user;' (still in your int main())
Call/use the functions you wrote in statfun.cpp (notably mean() and sd()). Maybe store their return values in a variable to use later. Since you need to call the statfun functions here, the lab1.cpp entry file must include statfun.h so that it knows what code to execute when you call those functions.
Now that this file structure logic is complete. A simple way to calculate std deviation in pseudocode:
statfun.madeuplanguage
type sd(vector<type> values) {
type total = 0;
type mean_value = mean(values);
for val in values {
total += (val - mean_value)^2;
}
total /= values.length;
return sqrt(total);
}
This in mind, I would structure the lab1.cpp as follows.
lab1.cpp
int main() {
vector<double> v;
// take input and store in v.
// std out - v
double mean_val = mean(v);
double std_dev = sd(v);
// std out - mean_val and std_dev
}
If you have any questions about implementing the above pseudocode in C++, great! It's your assignment/class, so take care to search the webs in doing extremely specific things in C++ (e.g. iterating on a vector, squaring, square rooting, etc...). Good luck learning.

C++ multiple definition of function in class definition

I just got into C++ and I was trying to write a simple code for a simulation, but I bumped into a multiple definition problem than I cannot solve.
So, I'm creating a class and this is the header file:
Piano.h
#ifndef PIANO_H
#define PIANO_H
#include"vettore.h"
#include"PuntoMat.h"
#include<string>
#include<vector>
class Piano
{
public:
//Costruttori
Piano(std::string material, float lenght, float inclin = 0)
: m_material(material), m_lenght(lenght), m_inclin(inclin), m_time(0) {;}
//Metodo per l'aggiunta di corpi al piano
void Add(PuntoMat p) { m_corpi.push_back(&p); }
//Metodo che stampa le coordinate dei corpi nel sistema
void Print();
private:
std::string m_material;
std::vector<PuntoMat*> m_corpi;
float m_lenght;
float m_inclin;
float m_time;
};
#endif
this is the corresponding file .cxx, where I define the function "Print"
Piano.cxx
#include"vettore.h"
#include"PuntoMat.h"
#include"Piano.h"
#include<iostream>
#include<stdlib.h>
#include<vector>
void Piano::Print()
{ std::cout << "Tempo: " << m_time << " s" << std::endl;
if(m_corpi.size() == 0)
{ std::cout << "Nessun corpo sul piano" << std::endl;
exit(1);
}
for(int i=0; i<m_corpi.size(); i++)
{ std::cout << *m_corpi[i] << std::endl;
}
std::cout << std::endl;
}
This is the code I'm using to validate the class
main.cxx
#include<iostream>
#include"vettore.h"
#include"PuntoMat.h"
#include"Piano.cxx"
#include<string>
main()
{
PuntoMat a(3, Vettore( 0, 0), Vettore( 5.4, 0), "Legno");
PuntoMat b(5, Vettore( 8.3, 6.5), Vettore( 0, 0), "Vetro");
Piano p( "Ferro", 50);
p.Add(a);
p.Add(b);
p.Print();
return 0;
}
When I compile I get a multiple definition error about the function Print, this one:
/tmp/ccp1giKM.o: In function `Piano::Stampa()':
main.cxx:(.text+0x0): multiple definition of `Piano::Stampa()'
/tmp/cctCJRQF.o:Piano.cxx:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
I really don't know how to solve this problem, since it seems to me that the function Print() has been defined only in the file Piano.cxx. Can anyone help me with this?
P.s. Ignore the general meaning of the code and the comments (they are in italian). All the other classes included have been already validate and there is no problem with them.
Your problem is that you try to include the cxx file. You should only include .h/.hpp files. Instead of include the source files you should tell your compiler to use it.
So in your case removing the "#include"Piano.cxx" line and than calling your compiler in this way(asuming g++),
g++ main.cxx Piano.cxx
should fix the problem. If you want to create bigger projects you should have a look at creating object files from your sources.

Static Initialization Fiasco - On Purpose

Just for fun, I was investigating the order of dynamic initialization of static objects.
In a file name t.h, I put
struct T {
static std::vector<std::string> me;
static int add(std::string s) { me.push_back(s); return me.size(); }
};
(Plus needed headers for vector and string.)
"std::vector T::me" is in t.cpp.
The file main.cpp prints out the values in T::me:
#include "t.h"
#include <iostream>
using namespace std;
int main()
{
T::me.push_back("main");
cout << "T::me.size()=" << T::me.size() << endl;
for (unsigned i = 0; i<T::me.size(); ++i) {
cout << i << "-" << T::me[i] << endl;
}
return 0;
}
next, I create "a.cpp" and put the following in it:
#include "t.h"
int a = T::add("a");
Do the similar for file b.cpp and c.cpp using "b" and "c" as appropriate.
Compile using g++ *.cpp, then run ./a.out. The order of static initialization from compilation unit to compilation unit is unspecified. In my case it is consistently in reverse alphabetical order. I get:
3 - c
2 - b
1 - a
0 - main
No problems so far.
Now I create u.cpp like a.cpp but using "u". Recompile/rerun, "u" does not show up in the list.
Is it because I never referenced u? I never referenced a,b,c, but I change main:
#include "t.h"
#include <iostream>
using namespace std;
extern int u;
int main()
{
cout << "u=" << u << endl;
T::me.push_back("main");
cout << "T::me.size()=" << T::me.size() << endl;
for (unsigned i = 0; i<T::me.size(); ++i) {
cout << i << "-" << T::me[i] << endl;
}
return 0;
}
The program prints out "u=2", but "u" is not in the list. Shouldn't u have been dynamically initialized before use and, therefore, T::me have been updated to include "u"? I think there should be a better explanation than that u comes after t in the alphabet.
I've got it. Simple, really.
T::me is zero initialized statically according to the rules of C++. There is a constructor, however, to run dynamically. There's no guarantee when that constructor runs. It is apparently - in this case - running after u is initialized.
It seems that the compilation linking order matters:
g++ -o m a.cpp u.cpp t.cpp main.cpp
gives
a=2
u=1
T::me.size()=3
0-u
1-a
2-main
but
g++ -o m main.cpp t.cpp a.cpp u.cpp
gives
a=2
u=1
T::me.size()=1
0-main
and reversing a.cpp and u.cpp in the last case causes a=1 and u=2.
Interesting!