I'm trying to teach myself C++ (actually I should say re-learn, but I first learned it when I didn't know a thing about coding and year ago so it doesn't count) and I'm doing my first project after finishing the online tutorial. I figured since I had a good C# and VB.Net background I might as well try something a bit bigger, but not too big. Before I start, I'm using Code::Blocks as my IDE and the default compiler in that IDE (I believe it's MinGW). So here is my thing : I have a ChromaTest project (this is using the Razer Chroma SDK for those wondering about the name) which is a console app, and a ChromaTestDLL project, which is (you guessed it) a DLL (I decided to do a DLL to learn how to do so at the same time and because I might use some the code in a GUI project later on). Problem is I'm getting a Segmentation Fault error when trying to insert into a map. Here is the relevant code :
In the ChromaTestDLL Project
MyChroma.h (Header for the MyChroma class)
#ifndef MYCHROMA_H
#define MYCHROMA_H
#include <map>
#include <windef.h>
#include "RzChromaSDKTypes.h"
#include <string>
#include "Template.h"
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
class DLL_EXPORT MyChroma
{
public:
MyChroma();
bool Init();
std::map<char, COLORREF> GetColorMapping();
void SetColorMapping(char key, COLORREF color);
void AssignToKeyBoard();
void SetColorFromString(string s, COLORREF color);
~MyChroma();
protected:
std::map<char, COLORREF>* _ColorMapping;
ChromaSDK::Keyboard::RZKEY KeyFromChar(char keyChar);
My_Chroma_Implementation* Chroma;
private:
};
#ifdef __cplusplus
}
#endif
#endif // MYCHROMA_H
MyChroma.cpp (Relevant implementation for MyChroma class)
#include "MyChroma.h"
#include "Template.h"
#include <iostream>
MyChroma::MyChroma()
{
_ColorMapping = new std::map<char, COLORREF>();
}
std::map<char, COLORREF> MyChroma::GetColorMapping() { return *_ColorMapping; }
void MyChroma::SetColorMapping(char key, COLORREF color){
if (_ColorMapping->count(key) == 0)
_ColorMapping->insert(std::make_pair(key, color)); //This where the error happens
else
(*_ColorMapping)[key] = color;
}
MyChroma::~MyChroma() {
delete Chroma;
delete _ColorMapping;
}
//Other implementations omitted
In the ChromaTest project
MyChroma.h (Header to import MyChroma class, slightly different from the one in ChromaTestDll, basically it only contains public members)
#ifndef MYCHROMA_H
#define MYCHROMA_H
#include <map>
#include <windef.h>
#include <string>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
class DLL_EXPORT MyChroma
{
public:
MyChroma();
bool Init();
std::map<char, COLORREF> GetColorMapping();
void SetColorMapping(char key, COLORREF color);
void AssignToKeyBoard();
void SetColorFromString(string s, COLORREF color);
~MyChroma();
};
#ifdef __cplusplus
}
#endif
#endif // MYCHROMA_H
Main.cpp (main app code)
#include <iostream>
#include "MyChroma.h"
#include <wingdi.h>
using namespace std;
int main()
{
MyChroma test = MyChroma();
bool result = test.Init();
cout << (result ? "Initialized\n" : "Failed to initialize Razer Chroma");
cout << "Setting color";
if (result){
test.SetColorMapping('a', RGB(255,0, 0)); //This call goes in the DLL where I said it failed earlier.
test.SetColorMapping('a', RGB(0,0,255));
}
return 0;
}
Sorry for the atrociously long code (please tell me if there are things I could have removed here). Can anybody spot any mistake in there I would not be surprised this would be linked to pointers, this is probably the concept which took me the most time to understand. At first I didn't put the map in a pointer and on the heap, but changing another variable to that earlier seemed to have fixed another problem so I figured I'd give it a try. Sadly I had pretty much the same errors when not putting the map on the heap too.
On a side note, can anybody explain to me what different between the heap and the stack, why would I want to go through the (risky) hassle of storing variables on the heap (with pointers and deletion and all) instead of on the stack, and when should I use the heap or when should I not.
Based on the information in your question:
The compiled code in your DLL appears to declare a MyChroma class containing a bunch of internal class members, in its header file.
Then your main application uses a completely different header file, that defines a class called MyChroma, stripped of its class members.
Then, your main application instantiates the MyChroma class, based on what it sees in its header files.
That's not going to work. Since your main application knows nothing about those class members, the actual class that it instantiates is too small.
And it instantiates a class on the stack.
And then the constructor comes from the DLL, which thinks the class contains all those other class members.
And the constructor in the DLL attempts to initialize them.
On the stack.
Hello stack corruption.
The answer here is simply "don't do what you did". This is undefined behavior. Everything that you compile that references a particular class must see an identical declaration (and inline method definitions) of the class.
Full stop.
No exceptions.
Well, with sufficient experience, it's possible to do something like this safely, when targetting a specific C++ implementation, but this is not the case here.
Until then, there are ways to hide the internal implementation details of library-provided classes, but this is not how you do it. The safe way to do it is with the PIMPL design pattern.
A few other thing you should not do, as well. This doesn't relate directly to the problem at hand, but this will avoid several other common pitfalls that can, without advance warning, pull the rug from under your feet:
Do not use use namespace std;. Especially in header files. Completely forget that something like that exists in the C++ language.
All your classes should also follow the Rule Of Three.
Related
So i am making a library for a hardware to be used with arduino. Inside that class there are some hardware specific code that needs to included. To improve readability i would like to move the hardware specific functions to another file
//.h
class myClass(){
public:
myClass();
void controlGPIO();
};
//.cpp
myClass::myClass(){
controlGPIO();
}
#ifdef HARDWAREA
#include "deviceA_hal.h"
#endif
#ifdef HARDWAREB
#include "deviceB_hal.h"
#endif
//deviceA_hal.h HardwareA functions
#include <deviceA_specific_Library>
void myClass::controlGPIO(){
// some code unique to hardwareA
}
//deviceB_hal.h HardwareB functions
#include <deviceB_specific_Library>
void myClass::controlGPIO(){
// some code unique to hardwareB
}
Is this possible ? Am i doing this correctly?
This would make adding more specific hardware easier and cleaner. Is there a more better way of doing it>?
Common is to do one .cpp with
#if defined(HARDWAREA)
#include "deviceA_hal.h"
#elif defined(HARDWAREB)
#include "deviceB_hal.h"
#endif
void myClass::controlGPIO(){
#if defined(HARDWAREA)
// some code unique to hardwareA
#elif defined(HARDWAREB)
// some code unique to hardwareB
#endif
}
this is simpler to maintain than two separate files
I recently came across something that goes against my understanding of includes.
I am creating a dll to hold basic coordinate objects for a personal game engine I'm developing (for fun).
Main dll header file.
#pragma once
#include "sclapi.h"
#include "vector.h"
#include "point.h"
// Other includes and stuff.
// Unimportant for this demonstration.
sclapi.h
#pragma once
#ifdef SCL_EXPORTS
#define SCL_API __declspec(dllexport)
#else
#define SCL_API __declspec(dllimport)
#endif
vector.h
#pragma once
// No includes
/*EDIT*/struct Point;
struct SCL_API Vector {
float x, y;
// Other stuff
explicit operator Point() const;
};
point.h
#pragma once
// No includes
struct SCL_API Point {
int x, y;
// Other stuff
explicit operator Vector() const;
};
My code works perfectly fine; but to my understanding, it shouldn't. A header file should only know what's declared in it (includes being shorthand for pasting in code). None of these objects are declared in the other's header files. [EDITED] point.h should have no knowledge of a Vector struct. Whats more, both even have knowledge of the SCL_API macro. If I comment out individual includes in the main header file, I get the expected compiler errors. What am I missing?
EDIT:
After further testing, I discovered that a declaration of the later objects needs to be in the first header file 'vector.h'; but after, they do not need to be declared again in any other header file. Also, declaring the classes in the main header file does not work. The Point forward declaration must be inside the vector.h file.
When you #include a file, it gets automatically "copypasted" into your source.
Because you included vector.h right before including point.h, the Point class will see it.
However, it's not a good idea to rely on this behavior as the order of includes might change and thus it will not work anymore, so you should #include "vector.h" in your point.h.
I'm currently writing a simple game with a 2D library and as C++ is a new language to me and as Java is my first fluent programming language, perhaps some bad habits are flowing through to this language that I don't fully understand. I have never had problems doing this in Java but in C++ it causes a ton of errors. As I don't want everything crammed into one class/header file, I've decided to split them up into packages and different classes, but I can't seem to do this without includng the same header files in different places. Here's an example.
Project.h
#ifndef PROJECT_H
#define PROJECT_H
#include "UIManager.h"//this is causing the error, when this, and the class instance is removed the program compiles and runs fine without error
using namespace gamelib;
class Project : public Game {
public:
Project(int argc, char* argv[]);
~Project();
void Update(int elapsed);
void Draw(int elapsed);
void Load();
/*Background*/
Texture * background;
Rectangle* backgroundRectangle;
UIManager ui;
};
#endif
UIManager.cpp
#include "UIManager.h"
void UIManager::load() {
startMenuBackground = new Texture();
startMenuBackground->Load("Sprites/Interface/Transparency.png", false);
startMenuRectangle = new Rectangle(0.0f, 0.0f, Graphics::GetWidth() / 2, Graphics::GetHeight() / 2);
}
UIManager.h
#ifndef UIMANAGER_H
#define UIMANAGER_H
#include "Project.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif
Now I need all of these includes so I can store the necessary textures, and the Texture and Rectangle come from the API that is being used as a namespace in Project.h
I also need a class instance in Project.h, UIManager ui; So i can use this in the Project.cpp file to call methods
How can I get around this without getting all these errors?
If I understand your problem correctly, you want to avoid including header files multiple times. In that case, what you should do is using Include guards. Which makes sure that the header is included once. Optionally you can use #pragma once at the top of your file but that's another discussion.
Example:
#ifndef UIMANAGER_H // you may choose another name than "UIMANAGER_H"
#define UIMANAGER_H
// Your header file code and includes here.
// Do this for your header files.
#endif
Now, do the same for the other header file but instead naming the macro PROJECT_H or similar.
A good practice is to add in the beginning and in the end of the .h files:
#ifndef FILENAME_H
#define FILENAME_H
//Your code here
#endif
Where FILENAME_H is unique for each .h file.
Those are compiler predirectives, which are not included in the executable, but changes the way that the compiler acts.
Adding those, the compiler won't add the same file twice for the same file. If it's already loaded, it won't load it.
Take in account than in C++, header files are parsed independently on each file of the project.
Typically, the fix would be to change your code to this...
#ifndef UIManager_H
#define UIManager_H
// It's pretty normal to put each class in its own header file.
#include "Texture.h"
#include "Rectangle.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
Since you never instantiate either object though, you don't strictly need a full header.
#ifndef UIManager_H
#define UIManager_H
// Since we only use pointers to the classes, we can forward declare the classes
class Texture;
class Rectangle;
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
You can use the macros #ifndef and #define. This is a common pattern. For example, in your UIManager.h file, have the following:
#ifndef __UI_MANAGER_H__
#define __UI_MANAGER_H__
#include "Project.h"
//Rest of UIManager class definition
#endif
In you Project.h file, have the following:
#ifndef __PROJECT_H__
#define __PROJECT_H__
#include "UIManager.h"
//Rest of Project class definition
#endif
This allows the compiler to compile without errors when it sees circular includes. But it's more preferable to use class forward declaration if possible, but this is a completely different topic.
The macro names __UI_MANAGER_H__ and __PROJECT_H__ are purely randomly chosen. You can choose to use a different naming convention.
I know what is going on, but I don't know how to fix this:
main.cpp
#include "Win32.h"
int main () {
return 0;
}
Win32.h
#include <windows.h>
#include <map>
#ifndef WIN32_H_
#define WIN32_H_
namespace W32 {
class Win32; // Pre-Declaration
std::map<HWND, Win32 *> windowMap; // Handle to Class instance mapping
class Win32 {
public:
Win32();
virtual ~Win32();
protected:
private:
}; // Class Win32
} // namespace W32
#endif // WIN32_H_
Win32.cpp
#include "Win32.h"
namespace W32 {
Win32::Win32() {
}
Win32::~Win32() {
}
} /* namespace W32 */
Error Messages:
src\Win32.o: In function `Win32':
D:\Dev\Projects\Eclipse\OpenGL3\Debug/../src/Win32.cpp:7: multiple definition of `W32::windowMap'
src\main.o:D:\Dev\Projects\Eclipse\OpenGL3\Debug/../src/main.cpp:14: first defined here
Ok, I get it that std::map<HWND, Win32 *> windowMap; is appearing in more the one file, and that because it is included in more then one file (main.cpp/Win32.cpp) it is causing it to be redefined. I am still somewhat new to std::map. What I need to do is prototype windowMap, but what I don't know is how? I thought this was when I grabbed this piece of code. The Win32 class needs to be able to use it, but it will have to be declared in order to do so, but what I have is not the way to do it, I am at a loss on what to look for to get the right information on how to properly forward declare std::map<HWND, Win32 *> windowMap.
std::map<HWND, Win32 *> windowMap;
is a definition, so you're breaking the one definition rule. You need to make the variable extern:
extern std::map<HWND, Win32 *> windowMap;
and define it in a single implementation file:
Win32.h
#include <windows.h>
#include <map>
#ifndef WIN32_H_
#define WIN32_H_
namespace W32 {
class Win32; // Pre-Declaration
extern std::map<HWND, Win32 *> windowMap; // Handle to Class instance mapping
//...
}; // Class Win32
} // namespace W32
#endif // WIN32_H_
Win32.cpp
#include "Win32.h"
namespace W32 {
std::map<HWND, Win32 *> windowMap; // Handle to Class instance mapping
//...
} /* namespace W32 */
The following is a deifnition, not a declaration:
std::map<HWND, Win32 *> windowMap;
Definitions go in cpp files; in the header you need a declaration, like this:
extern std::map<HWND, Win32 *> windowMap;
The definition
std::map<HWND, Win32 *> windowMap;
should go in the cpp file. Otherwise, each cpp file that includes the header with a definition will define its own windowMap, resulting in a linker error that you see.
The pure C++ method is to make:
std::map<HWND, Win32 *> windowMap"
a static member of Win32 class. In addition, forget about the file.h alongside with file.cpp, it has been deprecated by nearly every hardcore developer for sake of simplicity. Your code is so short, so everything should be included in the header, in especially when programming frameworks as you seems to do.
Your problem pop's up the reason why static members exists in C++. Furthermore defining this map extern is not good practice, cause you will also have to hide the real definition somewhere, maybe in a not so relevant place.
And finally, I've tried this design already, Windows handler's function get called in an asynchronous way ...
1- You will run in a race condition if more than one window is active at the same time.
2- In fact you'll run a race condition as soon as you call CreateWindow function, since it makes a call to your windows message pumping handler, in your back, and you don't know the HWND value yet
3- You will run a race condition if you try to insert/read/remove in the map at the same time, a quite common operation in fact.
I'm trying to write a dll that will store some values passed to it in between calls.
Currently, I have:
MyDll.h:
namespace MyDllNamespace
{
class MyClass
{
public:
static int getValue(int &a);
};
}
MyDll.cpp:
#include "ALERTDataAnalysisLibrary.h"
#include <stdexcept>
using namespace std;
namespace MyDllNamespace
{
int storedValue=0;
int MyClass::getValue(int &a)
{
a=a+storedValue;
}
}
MyDll.def
LIBRARY MyDllLibrary
EXPORTS
getValue #1
The idea is that the first time it is called, it returns the passed value, and the second time it's called it returns the sum of the passed value, and the previously passed value. (This is a bit cut down, the final version will have to work on arrays, and with more values, but one step at a time!)
I think what I want to do is stop getValue being static. Which would mean instantiating a class within the DLL (perhaps when it's loaded), and storing data in that. Then exposing a function of that class. I've no idea if that's the way to do it, I've not found anything like it after much searching.
You could export the whole class (and optionally use the pimpl idiom, but that's not mandatory):
In your DLL header file "MyDll.h", write the following:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MYDLL_API MyClass
{
...
};
Then, make sure that MYDLL_EXPORTS is defined in your DLL project only, so when you compile your DLL, your class is "dllexported", while when included in your main application, it's "dllimported".
Also, you won't need the .def file anymore.