Using extern and linking files - c++

So I am supposed to link these 3 files but when I run use.cpp and it tells me there is a problem with print_foo and print so there must be a problem with my linking or declarations;(FYI I am using Xcode to compile)
This is the header file
// my.h (HEADER FILE)
extern int foo;
void print_foo();
void print(int);
This is my.cpp
// my.cpp
#include "my.h"
#include "std_lib_facilities_5.h"
void print_foo() {
cout << foo;
}
void print(int i) {
cout << i;
}
int main() {
return 0;
}
And this is use.cpp
// use.cpp
#include "my.h" /* Declaration made available here */
int foo;
int main() {
foo = 7;
print_foo();
print(99);
return 0;
}

You did not mention how you are compiling them, on unix like systems you can do
$ gcc my.cpp use.cpp -o my
to compile

You must delete the main in
my.cpp
You can't have two main.

Related

How to use extern for declaring/defining global variable in C++ and CUDA

I have the following code structure composed of one .cpp, one .cu and one .hxx
UTILITIES.hxx
#ifndef UTILITIES_HXX
#define UTILITIES_HXX
namespace B{
extern int doors;
}
FILE2.cu
#include "utilities.hxx"
namespace A {
int foo (){
switch(B::doors){
//do something
}
}
}
FILE3.cxx
#include "utilities.hxx"
namespace B{
int doors=-1;
class Vehicle{
public:
void operation() {
doors++;
A::foo();
doors++;
A::foo();
}
}
}
I am declaring the doors variable as extern in the header and I am defining it in the .cxx file. So after that, the second .cpp should be able to use it. However I am getting the following error when linking:
/usr/bin/ld: ../src/libapp.a(FILE2.cu.o): in function A::foo(void)': /MYPATH/FILE2.cu:19: undefined reference to B::doors'
What am I doing wrong? Actually the foo function in the FILE2.cu is a normal C++ function, no CUDA involved at all.
missing #endif, missing return statement, no prototype for A::foo(), missing semicolon
These changes seem to work for me:
$ cat utilities.hxx
#ifndef UTILITIES_HXX
#define UTILITIES_HXX
namespace B{
extern int doors;
}
#endif
$ cat file2.h
namespace A {
int foo ();
}
$ cat file2.cu
#include "utilities.hxx"
namespace A {
int foo (){
switch(B::doors){
//do something
}
return 0;
}
}
$ cat file3.cpp
#include "utilities.hxx"
#include "file2.h"
namespace B{
int doors=-1;
class Vehicle{
public:
void operation() {
doors++;
A::foo();
doors++;
A::foo();
}
};
}
$ nvcc -shared file2.cu file3.cpp -Xcompiler -fPIC
$ nvcc -lib file2.cu file3.cpp
$
I can only work with what you have shown.

Simple C++ module system is not working correctly

I have implemented in C++ a simple module system (for demonstrative purpose only). Unfortunately the program is not working correctly (it produces not the expected output, it prints nothing out).
Here is my source code:
module.hpp
#ifndef _MODULE_HPP
#define _MODULE_HPP
#include <memory>
/// Interface for modules.
class Module {
public:
virtual void run() = 0;
virtual ~Module(){};
};
/// Symbol of the module construtor function.
const auto MODULE_CONSTRUCTOR_SYMBOL = "create_module";
/// Type of the module constructor function.
using MODULE_CONSTRUCTOR = std::unique_ptr<Module> (*)();
#endif /* _MODULE_HPP */
first.hpp
#ifndef _FIRST_HPP
#define _FIRST_HPP
#include <iostream>
#include "module.hpp"
class First : public Module
{
public:
First();
virtual ~First();
virtual void run();
std::unique_ptr<Module> create_module(void);
};
extern "C"
{
typedef std::unique_ptr<Module> create_first_module_t(void);
std::unique_ptr<Module> create_module(void);
}
#endif /* _FIRST_HPP */
first.cpp
#include "first.hpp"
First::First()
{
}
std::unique_ptr<Module> First::create_module()
{
auto ptr = std::unique_ptr<Module>{};
std::cout << "Creation of first module" << std::endl;
return ptr;
}
First::~First()
{
std::cout << "Destruction of first module" << std::endl;
}
void First::run()
{
std::cout << "Running the first module" << std::endl;
}
second.hpp
#ifndef _SECOND_HPP
#define _SECOND_HPP
#include <iostream>
#include "module.hpp"
class Second : public Module
{
public:
Second();
virtual ~Second();
virtual void run();
std::unique_ptr<Module> create_module(void);
};
extern "C"
{
typedef std::unique_ptr<Module> create_second_module_t(void);
std::unique_ptr<Module> create_module(void);
}
#endif /* _SECOND_HPP */
second.cpp
#include "second.hpp"
Second::Second()
{
}
std::unique_ptr<Module> Second::create_module()
{
auto ptr = std::unique_ptr<Module>{};
std::cout << "Creation of second module" << std::endl;
return ptr;
}
Second::~Second()
{
std::cout << "Destruction of second module" << std::endl;
}
void Second::run()
{
std::cout << "Running the second module" << std::endl;
}
main.cpp
#include <memory>
#include <dlfcn.h>
#include "first.hpp"
#include "second.hpp"
int main(void)
{
if (void* firstModule = dlopen("libFirst", RTLD_NOW))
{
if (create_first_module_t* createFirstModule = (create_first_module_t*)dlsym(firstModule, "create_module"))
{
std::unique_ptr<Module> firstModule(createFirstModule());
firstModule.get()->run();
}
dlclose(firstModule);
}
if (void* secondModule = dlopen("libSecond", RTLD_NOW))
{
if (create_second_module_t* createSecondModule = (create_second_module_t*)dlsym(secondModule, "create_module"))
{
std::unique_ptr<Module> secondModule(createSecondModule());
secondModule.get()->run();
}
dlclose(secondModule);
}
return 0;
}
Here are the instructions for the g++ compiler (on a linux machine):
g++ -Wall -Wextra -shared -fPIC first.cpp -o first.so -ldl
g++ -Wall -Wextra -shared -fPIC second.cpp -o second.so -ldl
g++ -Wall -Wextra -c main.cpp
g++ -o main main.o first.so -ldl
The expected output should be the following:
$ LD_LIBRARY_PATH=. ./main ./first.so
Creation of first module
Running the first module
Destruction of first module
$ LD_LIBRARY_PATH=. ./main ./first.so ./second.so
Creation of first module
Creation of second module
Running the first module
Running the second module
Destruction of first module
Destruction of second module
Something is wrong with my implementation, but I do not know where the mistakes are.
I hope that someone can help me with my problem.

Compile under Ubuntu with different header type

I have 3 files namely "main.cpp", "testclass.cpp" and "testclass.h". I compile the files by calling:
g++ testclass.cpp main.cpp
main.cpp
#include <iostream>
#include "testclass.hpp"
int main()
{
testclass foo(56);
std::cout << "Object in cpp\t" << numberobject.getNumber() << "\n";
return 0;
}
testclass header
#ifndef TESTCLASS_H
#define TESTCLASS_H
class testclass
{
private:
int number;
public:
testclass();
testclass(int);
int getNumber();
};
#endif //TESTCLASS_H
testclass.cpp
#include "testclass.hpp"
testclass::testclass()
{
}
testclass::testclass(int number)
{
this->number = number;
}
int testclass::getNumber()
{
return number;
}
There will be a compile error
testclass.cpp:7:1: error: prototype for ‘testclass::testclass(int)’ does not match any in class ‘testclass’
testclass::testclass(int number)
^
testclass.h:4:7: error: candidates are: testclass::testclass(const testclass&)
class testclass
^
testclass.cpp:3:1: error: testclass::testclass()
testclass::testclass()
^
However, if I change the "testclass.h" to "testclass.hpp" and also change all #include statment from #include "testclass.h" to #include "testclass.hpp", it works well.
Why I can't compile the .h file? And is there anyway to compile with .h file?
Finally, I found that there is a strange 'testobject.h.gch" file under the same directory. It works fine after I remove it.

Why do I not need to include main.cpp?

In the small example needsExtern.cpp needs the definition of global::bar. needsExtern.cpp would normally include the file with the definition (in this case main.cpp). However, since the file is main.cpp it is not needed.
Why does needsExtern.cpp not need to include main.cpp?
needsExtern.h
struct NeedsExtern
{
NeedsExtern();
};
needsExtern.cpp
#include "needsExtern.h"
#include <iostream>
namespace global
{
extern const int bar;
}
NeedsExtern::NeedsExtern()
{
std::cout << global::bar << "\n";
}
main.cpp
#include "needsExtern.h"
namespace global
{
extern const int bar{26};
}
void main()
{
NeedsExtern ne;
}
This is precisely where extern is invented for: the compiler just assumes the variable is defined elsewhere in the project. You can read more about this principle here.

Simple class usage+undefined reference

I have just created this simple class.When I compile, I am getting the following error.
caller.o: In function main':
caller.cpp:(.text+0x15): undefined reference toReader::Reader(int)'
collect2: ld returned 1 exit status
Reader.h
#ifndef READER_H
#define READER_H
class Reader
{
private:
int m_month;
Reader() {}
public:
Reader(int month);
void SetDate(int month);
int GetMonth() {return m_month;}
};
#endif
Reader.cpp
#include "Reader.h"
Reader::Reader(int month);
{
SetDate(month);
}
void Reader::SetDate(int month)
{
m_month=month;
}
main program
#include <iostream>
using namespace std;
#include "Reader.h"
int main()
{ int i;
i=5;
Reader rd(i);
i=rd.GetMonth();
cout<<i;
return 0;
}
There is a ; semicolon that should not be there.
Reader::Reader(int month)//; remove semicolon from this line !!!
{
SetDate(month);
}
You need to compile all your source files into object files, and then link the object files together to produce the program.
This can be done in one step:
gcc Reader.cpp main.cpp
Or in two separate steps:
gcc -c Reader.cpp main.cpp
gcc Reader.o main.o
Of course, you should normally have an IDE, Makefile or buildsystem generator (such as CMake) take care of this for you.