I am working on an assignment in my Object Oriented Programming class. One of the many instructions in the assignment was to take some of the teacher's code and break it into different modules/files. The instructions goes as follows:
The joblist module, consisting of the files joblist.cpp and joblist.hpp, should contain the global variables threshold and jobs, as well as the functions firstJobMeetingThreshold, removeJob, addJob, hasJob, and getJob. However, only the threshold variable and the addJob, hasJob, and getJob functions should be exported from this module. The remaining variables and functions are there as helpers.
I have the following code in my header file:
#include <iostream>
#include <vector>
using namespace std;
int threshold;
vector<Job> jobs;
int firstJobMeetingThreshold();
void removeJob(int i);
void addJob(Job job);
bool hasJob();
Job getJob();
(Job is an object from another class that does not need to be worried about)
The part that I am confused about with the assignment is how to make the specific functions exported and to how to make the others helpers. The functions are not supposed to be moved into another class or anything, so I am to go about this?
I am sorry if my instructions are unclear, I will provide any needed clarification. I am very new to OOP so I am still trying to figure out a lot of these concepts.
Regarding variables, you should add export before their declaration, for the ones you want to share with other source files. Specifically in your case, in the header file you should have
export int threshold;
To limit the functions scope, do you want to introduce a namespace? Otherwise you could remove the helper functions' declaration from the header file. If you do the latter, make sure that you define them in the source file before the first time you need to call them.
source => https://learn.microsoft.com/en-us/cpp/build/exporting-c-functions-for-use-in-c-or-cpp-language-executables?view=msvc-170
#ifdef __cplusplus
extern "C" { // only need to export C interface if
// used by C++ source code
#endif
__declspec( dllimport ) void MyCFunc();
__declspec( dllimport ) void AnotherCFunc();
#ifdef __cplusplus
}
#endif
Related
Well, I'm learning C++ and never really learned how to do stuff that is not OO.
I'm trying to get a bit more experience coding in C style.
GobalInformation.h
#pragma once
#ifndef GLOBALINFORMATION_H
#define GLOBALINFORMATION_H
#include "MapInformation.h"
namespace gi {
MapInformation mapInf;
};
#endif
I would like to be able to access gi::mapInf from every header and cpp in my project. Right now I'm including globalinformation.h in every header, so I'm getting linker errors with multiple definitions.
How can I work around the problem?
In header file only do
namespace gi {
extern MapInformation mapInf;
};
In CPP file provide the actual definition.
namespace gi {
MapInformation mapInf;
};
It will work as you intend.
If you are using the MapInformation across dynamic link library boundaries you might have to link against the library that includes the definition cpp file. Also on Window you might have to use dllimport/dllexport
Be aware that having globals in multiple compilation units can easily lead to order-of-initialization problems. You may wish to consider replacing each global with a function that returns a reference. In your case, put this in one cpp file and declare it in the header:
namespace gi {
MapInformation& getMapInf()
{
static MapInformation result;
return result;
}
}
Global variables are C, but namespaces are C++. There is a good discussion on using global variables and how they can be replaced by Singleton pattern: Globals and Singletons
And here is a simple sample: CPP/Classes/Singleton
Perhaps a better solution is to create a global object that contains all your global data. Then pass a smart pointer to the classes that actually need to access this shared global data.
Example:
class GlobalData
{
public:
int ticks_;
};
//Other file
class ThatNeedsGlobalData
{
public:
ThatNeedsGlobalData(std::shared_ptr<GlobalData> globalData);
};
This will save you some trouble.
Good luck!
Here are a few things that you need to take care of while trying to use global variables the way you have used.
Ensure that all the header files that the header files that GobalInformation.h includes are also enclosed insides #ifndefs. (I could not see mapinformation.h so I assume you have done it)
Just like CPP, C compiler also does not ensure order of the initialization of variables in different translation units(different C/CPP files).
Hence declare the header file as
//GlobalInformation.h
namespace gi {
extern MapInformation mapInf;
};
In a function that you know would be called first initialize the variable. This way lazy-initialization can also be acheived in C.
If we have a C++ DLL with 4 exported functions, what is the best way to construct an object of a class when the DLL is loaded (by LoadLibrary), in a way that we can access public methods of that class from within any exported function (exported by extern "C" __declspec(dllexport)). I remember global stuff is evil.
Looking for a better way of doing the following (the following is not the best approach):
namespace namespace_top_of_CMS_DLL{
CMS CMS_Object =CMS();
CMS*CMS_Ptr_Object =&CMS_Object;
}
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runFullStructure(){
namespace_top_of_CMS_DLL::CMS_Ptr_Object->runFullStructure();
}
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runSubStructures(){
namespace_top_of_CMS_DLL::CMS_Ptr_Object->runSubStructures();
}
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runReducedStructure(){
namespace_top_of_CMS_DLL::CMS_Ptr_Object->runReducedStructure();
}
First of all, don't use absolute statements like "globals are evil". What is a global anyway? Even globals have some scope. If that scope makes logical sense, then it's certainly not evil. main is not evil, for example. An exported DLL function is similarly a "global". If you need to interact with that module, you're going to need some kind of way to access it.
You'll need to export at least 1 function from the DLL to use it, and use GetProcAddress. From there, you have any number of patterns to follow. The simplest is to just export C-style functions as you need them.
If you need C++ objects, DLLs can create a huge amount of headaches. I would recommend either exporting everything as C-style, or using COM.
"Looking for a better way of doing the following (the following is not the best approach): ..."
I'd prefer to put the global class instances into an unnamed namespace in the translation unit where your exported functions are implemented.
Remove the declarations for CMS CMS_Object and CMS*CMS_Ptr_Object from the header file. Also have a separate translation unit for the implementation, and move the inline definitions of your exxported functions there
Header:
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runFullStructure();
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runSubStructures();
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runReducedStructure();
Implementation
namespace { // << note no namespace here
CMS CMS_Object =CMS();
CMS*CMS_Ptr_Object =&CMS_Object;
}
void OPS_CMS_DLL_runFullStructure(){
CMS_Ptr_Object->runFullStructure();
}
void OPS_CMS_DLL_runSubStructures(){
CMS_Ptr_Object->runSubStructures();
}
void OPS_CMS_DLL_runReducedStructure(){
CMS_Ptr_Object->runReducedStructure();
}
That way you can ensure, they can be accessed from your exported function implementations exclusively.
"I remember global stuff are evil."
It's true that global variables are an indication for bad design in most cases. These are prone to clutter code, and being unintentionally used from other code, which is out of your control.
Having module private globals is perfectly OK.
Be careful about exposing a class outside a dll. The C ABI is far simpler and far better defined than the complex C++ ABI. If templates are involved all guarantees go out the window.
So unless you want to commit to always using the same toolchain to compile your dll and exe, stick to your extern "C" __declspec(dllexport) method in your OP. For convenience you can always provide a C++ wrapper (header only).
I am using GCC C++ 11 in CodeBlocks IDE. I have been trying to reuse classes that I wrote by putting them into a header file but it doesn't work. I have looked into many books but none has detailed information on making C++ code reusable.
There are a couple concepts that C++ uses that I think you're missing:
The difference between a declaration and a definition
#include statements
Linking against other libraries
In general, one reuses code in C++ by Declaring a function in a header file (.h), Defining it in a source file (.cpp). The header file ("foo.h") is then included in both the source file (foo.cpp) and any other file you want to use something declared in it using and preprocessor include directive #include "foo.h". Finally if the source file in which the functions declared in the header file are defined is not a part of the source for the library or executable that you're compiling, you will need to link against the library in which it was built.
Here's a simple example that assumes that you don't need to link against an external library and that all files are in the same directory:
foo.h:
The class Foo is declared along with a member function foobar and a private member variable barM. In this file we're telling the world that there is a class named Foo, it's constructor and destructor are public, it has a member function named fooBar that returns an integer and it also has a private member variable named barM.
class Foo
{
public:
Foo();
~Foo();
int fooBar();
private:
int barM;
};
foo.cpp
The individual member functions for our class Foo are defined, we implement the things we declared in the header file. Notice the include statement at the top
#include "foo.h"
Foo::Foo()
{
barM = 10;
}
Foo::~Foo()
{
}
int Foo::fooBar()
{
return barM;
}
main.cpp
We use our class in a different file, again the header file is included at the top.
#include <stdio.h>
#include "foo.h"
int main(int argc, char *argv[])
{
Foo flub;
std::cout << "flub's fooBar is: " << flub.fooBar() << std::endl();
return 0;
}
The expected output from this would be:
flub's fooBar is 10.
As a general note, I haven't compiled this code, but it should be enough to give you a basic example of the ideas of declarations, definitions, and include statements.
Seeing as you're coming from Java, I'm actually betting that you got all of that already, the hard part is actually using code from a different c++ library, which is akin to Java packages. Setting this up requires exporting the symbols you desired to use in a different library. The way to do this is compiler specific, but is generally accomplished by defining a Macro in a different header file and then using that macro in the declaration of the item you'd like to export. For gcc, see reference GNU Reference Manual.
To extend the above example you create another header file: fooLibExport.h
#if BUILDING_LIBFOO && HAVE_VISIBILITY
#define LIBFOO_DLL_EXPORTED __attribute__((__visibility__("default")))
#elif BUILDING_LIBFOO && defined _MSC_VER
#define LIBFOO_DLL_EXPORTED __declspec(dllexport)
#elif defined _MSC_VER
#define LIBFOO_DLL_EXPORTED __declspec(dllimport)
#else
#define LIBFOO_DLL_EXPORTED
#endif
foo.h would then be changed to:
#include "fooLibExport.h"
class LIBFOO_DLL_EXPORTED Foo
{
public:
Foo();
~Foo();
int fooBar();
private:
int barM;
};
Finally you'll need to link against the library that Foo was built into. Again this is compiler specific. At this point we're through the setting up of header files for exporting symbols from a C++ library so that functions defined in one library can be used in another. I'm going assume that you can follow the reference material for setting up the GCC compiler for the rest of the process. I've tried to bold the key words that should help refine your searches.
One final note about #include statements, the actual argument isn't just the filename, its the path, relative or absolute, to the file in question. So if the header file isn't in the same file as the file you're trying to include it in, you'll need to use the appropriate path to the file.
Code re-usability casts its net wide in C++ terminology. Please be specific what do you mean by it.C and C++ programming language features usually considered to be relevant to code reuse could be :-
functions, defined types, macros, composition, generics, overloaded functions and operators, and polymorphism.
EDITED IN RESPONSE TO COMMENT:-
Then you have to use header files for putting all declarations which you can use in any file just by including this.
I am currently looking through the code written by senior engineer. The code works fine but i am trying to figure out one detail.
He uses quite a few global variables and his code is broken down into a lot of separate files. So he uses a technique to make sure that global vars are declared everywhere where he needs to access them but are only defined once.
The technique is new to me but I read few articles on the internet and got some understanding about how it works. He uses
#undef EXTERN
followed by conditional definition of EXTERN as an empty string or actual extern. There is a very good article here explaining how it works. Also there is a discussion here
What gets me confused is that all examples I saw on the web suggest to include header file in a regular way in all of the source files that need it except for one. In this single special case line that includes header is preceded by definition of a symbol that will ensure that EXTERN will be defined to an empty string and .. so on (see link above). Typically this single special case is in main or in a separate source file dedicated to the declaration of global variables.
However in the code that I am looking at this special case is always in the source file that corresponds the header. Here is the minimal example:
"peripheral1.h" :
#undef EXTERN
#ifndef PERIPHERAL_1_CPP
#define EXTERN extern
#else
#define EXTERN
#endif
EXTERN void function1(void);
"peripheral1.cpp" :
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
function1()
{
//function code code here
}
Everywhere else in the code he just does
#include "peripheral1.h"
My question is how and why does that work? In other words, how does compiler know where to define and where to just declare function (or variable, or class ...)? And why is it ok in above example to have the lines :
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
in actual peripheral1.cpp rather then in main.cpp or elsewhere?
Or am I missing something obvious here?
All the source files, except "perripheral1.cpp", after preprocessing contain a sequence
of external variable declarations like:
extern int a;
extern int b;
extern int c;
In peripheral1.cpp only, after preprocessing, there will be a sequence of declarations:
int a;
int b;
int c;
int d;
which are tentative definitions of the corresponding variables, which, under normal circumstances are equivalent of the external definitions :
int a = 0;
int b = 0;
int c = 0;
int d = 0;
End result is, variable are declared everywhere, but defined only once.
PS. To be perfectly clear ...
In other words, how does compiler know where to define and where to
just declare function (or variable, or class ...)?
The compiler knows where to declare, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a declaration.
The compiler knows where to define, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a definition.
In other other words, the compiler does not know - you tell it explicitly what you want it to do.
Nostalgia
Ahh, this takes me back a fair way (about 20 years or so).
This is a way for C code to define global variables across multiple files: you define the variable once using a macro to ensure it is defined exactly only once, and then extern it in other C code files so you can utilise it. Nowadays it is quite superfluous in many instances, however it still has its place in legacy code, and will (most likely) still work in many modern compilers, nut it is C code not C++.
Normally the likes of #define PERIPHERAL_1_CPP is utilised to ensure uniquenesss of inclusion like a #pragma once
In my own code I would use something like:
#ifndef PERIPHERAL_1_CPP
#define PERIPHERAL_1_CPP
// my includes here
// my code here
#endif
That way you can #include the file as many times as you want all over your code, in every code file even, and you will avoid multiple definition errors. To be fair I normally do it with the .h files and have something like:
// for absolutely insane safety/paranoia
#pragma once
// normally sufficient
#ifndef PERIPHERAL_1_H
#define PERIPHERAL_1_H
// my includes here
// my code here
#endif
I have never tried it on cpp files but wil llater tonight to see if there is any benefit one way or the other:)
Give me a shout if you need any more info:)
I have a class imgmanager that allows me to load all my images exactly once, it's quite nice, and while prototyping I had all of my files in one place, so I didn't have to worry about cyclical definitions. However after separating all of my classes I have a problem.
My Header File
#ifndef IMAGEMANAGER_H
#define IMAGEMANAGER_H
#include "Img.h"
#include <vector>
#include <map>
#include <string>
class imgmanager{
protected:
std::vector<sf::Image*> images;
std::map<std::string,int> positions;
public:
sf::Image* addimg(std::string path); //relative to resources
sf::Image* getimg(std::string path);
int size();
virtual ~imgmanager();
sf::Image* operator[](int);
}imagemgr;
#endif
With the instance created after the } and before the ; my compiler complains at me:
So I ask: What should I do to have a global instance of my imagemgr class? Should I just make a global header file and create an instance? (in this particular case I can just make a global variable in my main.cpp, none of the headers require the instance)
Don't create object instances in headers.
Create your object instance in one source file.
If you need to access it across multiple Translation Units, put this in your header:
extern imgmanager imagemgr; // declaration
This will inform all code that can "see" the header that there exists a so-named object; but it will still only actually be defined in the one source file where you wrote:
imgmanager imagemgr; // definition
(This is analogous to the way in which you declare functions in a header, but define them in precisely one source file:
void f(); // declaration
void f() { ... } // definition
)
The above general advice dutifully imparted, I would now question the rationale of having a class at all if you're only going to use one, single, global instance of it. Either make it a "singleton" class, or use free functions in a namespace instead.
If you require a single global instance, i suggest you make the ImageManager a "Singleton".
I'm unsure what to do for complex types, but for a global declaration of a simple data-type you should declare the variable "extern" in the header, and instantiate it in exactly one module (.cpp file).