I am trying to create and link a static library in C++. I have two files:
helloWorld.cpp
#include <iostream>
int main(int argc, char const *argv[]) {
std::cout << "I'm inside main." << '\n';
printHello();
return 0;
}
libraryHello.cpp
#include <iostream>
void printHello() {
std::cout << "Hello" << '\n';
}
I am running such commands (based on http://www.techytalk.info/c-cplusplus-library-programming-on-linux-part-one-static-libraries/):
g++ -Wall -c libraryHello.cpp -o libraryHello.o
ar rcs libmylib.a libraryHello.o
g++ -static helloWorld.cpp -L. -lmylib -o helloExecute
First two go well, when trying to compile main file such error appears:
helloWorld.cpp: In function ‘int main(int, const char**)’:
helloWorld.cpp:5:14: error: ‘printHello’ was not declared in this scope
It looks as though it is not loaded at all and it cannot find printHello. Is there anything I am doing wrong when compiling, linking or anything else? What I want to do is to call printHello() procedure from main using static library and linking it to helloWorld.cpp.
My compiler: g++ 5.4.0, OS: Ubuntu 16.04 32bit
You did not declare the function before use:
#include <iostream>
void printHello(); /// <-- this was missing
int main(int argc, char const *argv[]) {
std::cout << "I'm inside main." << '\n';
printHello();
return 0;
}
You have everything in place that is needed for linking, but not for compiling. The general idea is like this: The compiler needs a declaration for every function that you use. That is, it has to know its name and signature.
The compiler will now check whether a function call is valid for the given signature and leave a placeholder for the function call. It is up to the linker to resolve those placeholders and replace them with the actual address of the called function.
The linker therefore has to find a matching definition for that function, that is, an actual implementation. If you just declare the function, but forget to define it, compilation will happily succeed, but the linker will complain about an unresolved reference.
This split allows you to compile different source files in isolation: Each source file needs to know the declarations of every function that it uses, but not the definitions. This is enough for the compiler to ensure that a caller uses the function correctly. Declarations are typically placed in header files, to ensure that implementation and caller have a consistent understanding about what the function signature is, even if they reside in distinct source files.
helloWorld.cpp
#include <iostream>
#include <libraryHello.h>
using namespace std;
int main(int argc, char const *argv[])
{
cout << "I'm inside main." << '\n';
printHello();
return 0;
}
libraryHello.h (You need add this file)
#ifndef LIBRARYHELLO_H
#define LIBRARYHELLO_H
void printHello();
#endif // LIBRARYHELLO_H
libraryHello.cpp
#include <iostream>
#include <libraryHello.h>
void printHello() {
std::cout << "Hello" << '\n';
}
You still need to have a forward declaration for
void printHello();
before main().
Otherwise the compiler doesn't know how that function should be called.
The usual way is to put that into a corresponding header file, and include that in the other translation units.
Related
I am trying out a simple program to print the timestamp value of steady_clock as shown below:
#include <iostream>
#include <chrono>
using namespace std;
int main ()
{
cout << "Hello World! ";
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
cout<<"Value: " << now << endl;
return 0;
}
But whenever I am compiling like this g++ -o abc abc.cpp, I am always getting an error:
In file included from /usr/include/c++/4.6/chrono:35:0,
from abc.cpp:2:
/usr/include/c++/4.6/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the upcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
abc.cpp: In function âint main()â:
abc.cpp:7:3: error: âuint64_tâ was not declared in this scope
abc.cpp:7:12: error: expected â;â before ânowâ
abc.cpp:8:22: error: ânowâ was not declared in this scope
Is there anything wrong I am doing?
Obviously, I'm not following certain best practices, but just trying to get things working for you
#include <iostream>
#include <chrono>
#include <cstdint> // include this header for uint64_t
using namespace std;
int main ()
{
{
using namespace std::chrono; // make symbols under std::chrono visible inside this code block
cout << "Hello World! ";
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
cout<<"Value: " << now << endl;
}
return 0;
}
and then compile using C++11 enabled (c++0x in your case)
g++ -std=c++0x -o abc abc.cpp
You should include stdint.h file.
If you really want to include, add "#define __STDC_LIMIT_MACROS"
Ref: https://stackoverflow.com/a/3233069/6728794
I'm working on making a game in C++. I have declared a Constant namespace used for global values that I need access to throughout the program. In there I have an ofstream for debugging purposes (yeah, I know it's not "constant" but it fits best there), which outputs only when it feels like it. I was able to make a small program demonstrating the problem. I apologize for it being spread across 4 files, but it is important, I promise.
main.cpp:
// Include necessary files
#include "test.h"
#include "constants.h"
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
// Start of program
Constant::outstream.open("test.txt");
// ...
// Do stuff
// Output debugging info
Test test;
test.print("Test", Constant::outstream);
// ...
// Do other stuff
// End of program
Constant::outstream.close();
return 0;
}
constants.h:
#ifndef _CONSTANTS_H
#define _CONSTANTS_H
#include <fstream>
namespace Constant
{
static ofstream outstream;
}
#endif
test.h:
#ifndef _TEST_H
#define _TEST_H
#include <string>
#include <fstream>
#include "constants.h"
class Test
{
public:
void print(string str, ofstream& out);
};
#endif
test.cpp:
#include "test.h"
using namespace std;
void Test::print(string str, ofstream& out)
{
out << "out: " << str << endl << flush; // Works
Constant::outstream << "Constant::outstream: " << str << endl << flush; // Doesn't
}
In the test.cpp file, the out << ... line works as it should, while the Constant::outsream << ... line doesn't do anything even though I'm passing Constant::outstream as the out parameter! I don't see any reason why these two lines should be in any way different.
Before posting this, I tried putting test.cpp's code in test.h, just to have less files for the question, and was amazed to see it work. If I copy-paste the Test::print() function into test.h (whether inside or out of the class Test { ... }), then both output commands work correctly. the problem only occurs if Test::print()'s implementation is in a separate file.
It seems like any references to Constant::outstream simply don't work in class cpp files (no compile error, just nothing happens). It works in main.cpp and in class header files, but any class cpp file it seems not to. Unfortunately, this is a big program I'm writing so pretty much every class has its own cpp implementation file, and that's really the one place I need to use this ofstream. Does anyone know the reason for this?
Thanks in advance,
Doug
Constant::outstream has internal linkage, thus a separate instance is created for each translation unit. In short, Constant::outstream in test.cpp and main.cpp are two different variables.
§3.5.2 A name having namespace scope (3.3.6) has internal linkage if it is the name of
— a variable, function or function template that is explicitly declared static; or,
On the other hand, static class members would be visible throughout the program.
So, if you would write
struct Constant
{
static ofstream outstream;
}
instead of
namespace Constant
{
static ofstream outstream;
}
it would work.
However, note that the class must have external linkage; e.g. you should not put in in anonymous namespace.
I'm on Linux, the question is concerning shared objects of C++ classes.
The problem comes when my shared objects try to use resources linked into the main executable. I have the following codes:
loader.cpp:
#include <dlfcn.h>
#include <iostream>
#include "CommonInfo.h"
using namespace std;
int main(int argc, char** argv) {
for(int i=1; i<argc; ++i) {
string pth = "./";
pth.append(argv[i]);
void* dh = dlopen(pth.c_str(), RTLD_NOW);
if(dh==NULL) {
cerr << dlerror() << endl;
return 1;
}
CommonInfo::GetInfoFunc getInfo = (CommonInfo::GetInfoFunc)(dlsym(dh,"getInfo"));
if(getInfo==NULL) {
cerr << dlerror() << endl;
return 1;
}
CommonInfo* info = getInfo();
cout << "INFO: " << info->getX() << endl;
delete info;
}
return 0;
}
CommonInfo.h:
#include <string>
class CommonInfo {
public:
typedef CommonInfo* (*GetInfoFunc)();
private:
std::string x;
public:
CommonInfo(const std::string& nx);
std::string getX() const;
};
EDIT:
I accidentaly forgot to ctrl-c + ctrl-v the source of CommonInfo.cpp here. Of course, it is there during compilation, so CommonInfo.cpp:
#include "CommonInfo.h"
CommonInfo::CommonInfo(const std::string& nx) : x(nx) {
}
std::string CommonInfo::getX() const {
return x;
}
A Plugin.h header:
#include "CommonInfo.h"
extern "C" CommonInfo* getInfo();
A very simple Plugin.cpp:
#include <iostream>
#include "Plugin.h"
#include "CommonInfo.h"
using namespace std;
CommonInfo* getInfo() {
return new CommonInfo("I'm a cat!");
}
Compiling is done with:
g++ -rdynamic -ldl -Werror CommonInfo.cpp loader.cpp -o loader
g++ -shared -fPIC -Werror Plugin.cpp -o Plugin.so
Running:
./loader Plugin.so
And there goes the error:
./loader: symbol lookup error: ./Plugin.so: undefined symbol: _ZN10CommonInfoC1ERKSs
Indeed, looking inside Plugin.so with nm Plugin.so | grep -i CommonInfo it gives an 'U' for this symbol (unresolved), which is perfectly ok.
Also, looking inside the binary of loader with nm loader.so | grep -i CommonInfo I could find the symbol with 'T', which is also ok.
Question is, shouldn't dlfcn.h unresolve the symbol in question from the main binary? Without this feature it becomes quite hard to use these stuff... Do I have to write a class factory function for CommonInfo, load it with dlfcn from the plugin and call that?
Thanks in advance,
Dennis
I haven't looked closely at your code, but I have in the past found behavior like you describe in the title when I did not link the executable with -E. (Or -Wl,-E when linking with gcc rather than ld.)
Note that not all platforms let the shared libraries take symbols from the calling binary. Linux and the *BSDs allow you to. But if you ever want to port to, say, Windows, you will not be able to use this pattern. I believe there are also some Unix-type OS's that won't let you do this. (It's been a while so I don't remember... Maybe it was Solaris?)
I have 1 cpp file with main().
It relies on structs and functions in another (say, header.hpp).
The structs are defined in header.hpp, along with function prototypes. The functions are implemented in header.cpp.
When I try to compile, I get an error message saying:
undefined reference to `see_blah(my_thing *)`
So to give an overview:
header.hpp:
#ifndef HEADERDUR_HPP
#define HEADERDUR_HPP
struct my_thing{
int blah;
};
int see_blah(my_thing*);
#endif
header.cpp:
#include "header.hpp"
int see_blah(my_thing * thingy){
// ...
}
main.cpp:
#include <iostream>
#include "header.hpp"
using namespace std;
int main(void)
{
thinger.blah = 123;
cout << see_blah(&thinger) << endl;
return 0;
}
I have no idea what I'm doing wrong, and I can't find any answers. Thanks for any answers, they are very much appreciated!
You should be aware that you're missing a semi-colon at the end of your structure definition. This means it's folding the two (supposedly separate) parts together and that you're not getting the function prototype as a result.
The following compiles fine (after fixing a couple of other errors as well):
// main.cpp
#include <iostream>
#include "header.hpp"
using namespace std; // <- not best practice, but irrelevant here :-)
int main(void)
{
my_thing thinger; // <- need this!
thinger.blah = 123;
cout << see_blah(&thinger) << endl;
return 0;
}
// header.cpp
#include "header.hpp"
int see_blah(my_thing * thingy){
// ...
}
// header.hpp
#ifndef HEADERDUR_HPP
#define HEADERDUR_HPP
struct my_thing{
int blah;
}; // <- see here.
int see_blah(my_thing*);
#endif
with:
g++ -o progname main.cpp header.cpp
gcc actually gave an error with that code you posted so I'm not certain why your compiler didn't. That command line above is also important - if you're compiling and linking in one step, you need to provide all required C++ source files (otherwise the linker won't have access to everything).
Your code is fine. You're just compiling it wrong. Try:
g++ main.cpp header.cpp
You need to:
#include "header.hpp"
in your *main.cpp file.
If you have included header.hpp, than probably you haven't link it(header.cpp) with main.cpp. What environment are you using(g++ or VC++)?
Edit:for linking in g++ you must write:
g++ main.cpp header.cpp -o program
Also you are missing semicolon in the end of your struct!
thinger.blah = 123; should be along the lines of:
my_thing thinger = { 123 };
in addition to issues other posters have mentioned. please, update your example so it compiles.
You are missing a semi colon at the end of your structure definition and mixing it with the method.
I'm trying to run my very first c++ program in linux (linux mint 8). I use either gcc or g++, both with the same problem: the compiler does not find the library I am trying to import.
I suspect something like I should either copy the iostream.h file (which I don't know where to look for) in the working folder, move my file to compile somewhere else or use an option of some sort.
Thanks for your suggestions.
Here's the gcc command, the c++ code, and the error message:
gcc -o addition listing2.5.c
.
#include <iostream.h>
int Addition(int a, int b)
{
return (a + b);
}
int main()
{
cout << "Resultat : " << Addition(2, 4) << "\n";
return 0;
}
.
listing2.5.c:1:22: error: iostream.h: No such file or directory
listing2.5.c: In function ‘main’:
listing2.5.c:10: error: ‘cout’ undeclared (first use in this function)
listing2.5.c:10: error: (Each undeclared identifier is reported only once
listing2.5.c:10: error: for each function it appears in.)
Now the code compiles, but I cannot run it from the command line using the file name. addition: command not found Any suggestion?
cout is defined in the std:: namespace, you need to use std::cout instead of just cout.
You should also use #include <iostream> not the old iostream.h
use g++ to compile C++ programs, it'll link in the standard c++ library. gcc will not. gcc will also compile your code as C code if you give it a .c suffix. Give your files a .cpp suffix.
please use g++ not gcc to compile it
You need <iostream> not <iostream.h>.
They are also header files not libraries.
Other things to fix, cout should be std::cout and you should use std::endl instead of "\n".
You need <iostream>, <iostream.h> is non-standard too-old header. Try this:
#include <iostream>
int Addition(int a, int b)
{
return (a + b);
}
int main()
{
using namespace std;
cout << "Resultat : " << Addition(2, 4) << "\n";
return 0;
}
If you don't want to use std alongside cout as below-
std::cout << "Hello World";
You can also define std at beginning of program by 'using namespace' keywords as-
#include <iostream >
using namespace std;
int Addition(int a, int b)
{
return (a + b);
}
int main()
{
cout << "Result : " << Addition(2, 4) << "\n";
return 0;
}
Now you need not to write std,everytime you use I/O operations.