I am creating a simple library for Arduino, the intent of which is to wrap and hide another class inside of it. I would like to be able to hide the underlying class entirely from the end user.
I have somewhat simplified this example to keep things clear, but the same problem exists.
The class I am trying to wrap is the Wire library which is called TwoWire.
The header file of the wrapper library:
#ifndef __DERIVEDONEWIRE2_H__
#define __DERIVEDONEWIRE2_H__
#include <Wire.h>
class DerivedWire
{
private:
TwoWire wire;
public:
DerivedWire();
};
#endif
The CPP file:
#include "DerivedWire.h"
DerivedWire::DerivedWire()
{
}
And the Arduino sketch that uses it:
#include <DerivedWire.h>
DerivedWire derivedWire;
void setup()
{
}
void loop()
{
}
This fails to compile:
/Users/andrew/Documents/Arduino/libraries/DerivedWire/DerivedWire.h:9:
error: 'TwoWire' does not name a type
Including Wire.h at the top of the main sketch allows this to compile:
#include <DerivedWire.h>
#include <Wire.h>
DerivedWire derivedWire;
void setup()
{
}
void loop()
{
}
However I would like to completely hide from the user of the DerivedWire library that the Wire library/TwoWire class is used at all.
I have tried changing the line "TwoWire wire;" to "TwoWire* wire;" - now I get the following error:
/Users/andrew/Documents/Arduino/libraries/DerivedWire/DerivedWire.h:9:
error: ISO C++ forbids declaration of 'TwoWire' with no type
/Users/andrew/Documents/Arduino/libraries/DerivedWire/DerivedWire.h:9:
error: expected ';' before '*' token
I've tried a few other things, but it just seems that I need to include Wire.h at the top level.
How do I fix this?
The Wire instance is created on the last line in the lib.
https://github.com/lstoll/arduino-libraries/blob/master/Wire/Wire.cpp
You are NOT supposed to have multiple instances of TwoWire, and there is no reason to hide it, but if you really want to hide it, you have to remove that line.
The arduino build method requires that the lib is included from the main sketch so you can not hide that part without signifigant changes.
If you really really need to hide this Wire instance, you could copy the source of the Wire lib into your own lib, and remove that last line.
Check out the "pimpl idiom", here's a link to get you started: http://en.wikipedia.org/wiki/Opaque_pointer
Pimpl idiom is a way in C++ to hide a class implementation, and all functions that you do not want to be visible.
Related
I am trying to use a function from another class but my dependencies seem to be stopping me.
main.cpp
#include "gesture.hpp"
#include "statemachine.hpp"
Gesture g;
StateMachine sm(g);
gesture.hpp
#include "hand.hpp"
statemachine.hpp
#include "gesture.hpp"
StateMachine(Gesture&);
Gesture *g;
What I am trying to accomplish:
I am trying to use a function from the StateMachine sm that I have declared. This function would be called inside a function in gesture.cpp and I would be giving my Gesture g class a pointer to StateMachine sm. (I would do this after I declare sm in main) I am able to #include "statemachine.hpp" in my gesture.cpp file but I want to move it to gesture.hpp so I can have it as a pointer that is stored as a variable in that class.
So when I do
gesture.hpp
#include "hand.hpp"
#include "statemachine.hpp"
I get the error 'Gesture' does not name a type and expected ')' before '&' token StateMachine(Gesture&);
Can anyone figure out what is going on? I can't move my function to gesture.cpp because it uses an array that is stored in my statemachine.hpp
You didn't provide the details so i will post my guess here.
When the precompiler analyze "gesture.hpp", it will unroll it to something like this:
codes in hand.hpp
StateMachine(Gesture&);
Gesture *g;
the file "gesture.hpp" is not unrolled in statemachine.hpp because i think you had provided some protections against circular dependency. so the compiler don't know what Gesture is.
To solve the compiling error, you can put a forward declaration of Gesture to statemachine.hpp, like this:
class Gesture;
StateMachine(Gesture&);
Gesture *g;
The Situation
I am writing a wrapper library for GPIB communications for setting up specific instruments according to a clients specifications to automate some of their processes. I have to use C++ and the old '98 compiler in VC++ 6.0 running on a Windows NT machine to maintain compatibility with some other devices they use regularly.
I am trying to make a class that combines some GPIB commands into easier to remember functions, while also keeping the capability of directly communicating with the instruments. To that end, I have compiled different parts of my project into different libs and dlls, each dll being a different device that they might want to communicate with. I also made a generic dll base class from which all the specific instrument classes inherit, hopefully making the whole setup as modular as possible.
The Problem
So, with all that said, I have an issue when I try to test the different dlls/modules. I created a project to test the generic base class, added the .lib file to the project, which links to the .dll, and also #included the header file for that dll. testGeneric.cpp looks like this:
#include "GENERIC.h"
void main(void) {
GPIBInstrument hp(2); //connects to device at primary address #2
hp.write("*IDN?");
}
Super simple. To be clear, I also have the GENERIC.lib linked in the "Resource Files" folder in VC++ 6.0, and I have GENERIC.dll accessible from the path variable.
Moving on, GENERIC.h looks like this (select parts):
#ifndef GENERIC_H
#define GENERIC_H
#include <string>
#include <windows.h>
#include "decl-32.h"
#ifdef GENERIC_EXPORT
#define GENERIC_API __declspec(dllexport)
#else
#define GENERIC_API __declspec(dllimport)
#endif
...(Inline exception classes)...
class GENERIC_API GPIBInstrument {
...
public:
void write(std::string command);
...
};
#endif
Just showing the relevant methods. Then GENERIC.cpp:
#define GENERIC_EXPORT
#include "GENERIC.h"
...
void GPIBInstrument::write(std::string command) {
ibwrt (handle, &command[0u], command.length());
std::cout << command << std::endl;
if (ibsta & TIMO) {
timeoutError();
}
if (ibsta & ERR) {
error("Unable to write command to instrument: " + command);
}
}
So, looks pretty good right? No issues. Compiles fine. I try running it, and BLAM! I get this: "User breakpoint called from code at 0x77f7645c". So, then I thought, well maybe it would work if I put all the code from GENERIC.h and GENERIC.cpp into one file, and #included that file all as inline code. So I tried it, and it and it compiled nicely, and ran fine.
Question (<-AHA!... But...)
What am I doing wrong!? Something with the way I'm making the .dll? Or the .lib? Or something else entirely?
EDIT (WHY!?)
So, after a bit of debugging, I found that it was something to do with passing a string literal. So I just modified it to:
std::string command = "*IDN?";
hp.write(command);
and it worked fine. My followup question, is why? What's the difference between having a string literal passed, versus assigning that to a variable and then passing it in?
Using complex types such as std::string as a parameter at a DLL boundary is tricky. You must ensure that the exe and the DLL use the exact same instance of the library code. This requires that you build them both to use the same version of the DLL version of the runtime library.
I am making some project using SFML. I have downloaded library from their official site, using cmake I made VS10 project, compiled it and got all the libs and files I need. However, in my project I keep getting nonsense errors like
class "sf::SoundBuffer" has no member "LoadFromFile"
class "sf::Sound" has no member "SetBuffer"
even though I have checked in SoundBuffer header there is a function named LoadFromFile and in Sound there is a function called SetBuffer.
SoundM::SoundM(void)
{
buffer.LoadFromFile("ress/soundA.wav");
collision.SetBuffer(buffer);
}
#ifndef SOUND_H
#define SOUND_H
enum Sounds {
PaddleCollision,
Losing
};
class SoundM {
public:
SoundM(void);
void play(Sounds Sound);
private:
sf::SoundBuffer buffer;
sf::Sound collision;
};
#endif
What am I missing here?
I assume that you are using the SFML version 2.0 RC. There was a name convention change and now, all function names start with a lowercase letter (camel case).
So you should try that.
buffer.loadFromFile("ress/soundA.wav");
collision.setBuffer(buffer);
Instead of that.
buffer.LoadFromFile("ress/soundA.wav");
collision.SetBuffer(buffer);
I hope that helps you!
I think this would increase the quality of life when devving, but google came up with nothing and I couldn't find anything specific inside inside Netbeans either.
What I want is to start with this header:
class bla
{
public:
static void gfg(somearg asd);
};
Then I open the blank bla.cpp and pressed 'autoimplement'. After that, it would look like this:
#include "bla.h"
static void bla::gfg(somearg asd)
{
//TODO: implement
throw unimplemented("void bla::gfg(somearg) is unimplemented");
}
Anyone know of a tool like this?
I found http://www.radwin.org/michael/projects/stubgen/
"stubgen is a C++ development tool that keeps code files in sync with their associated headers. When it finds a member function declaration in a header file that doesn't have a corresponding implementation, it creates an empty skeleton with descriptive comment headers."
This looks like it does exactly what you want it to do.
Some time has passed and in the meantime the requested feature seems to have been implemented in netbeans. Refer to https://netbeans.org/bugzilla/show_bug.cgi?id=213811 , which also gives a description on how to use it:
Note:
Implemented CTRL+SPACE.
IDE suggest implementing of class method if CTRL+SPACE was pressed:
- inside file that already has at least one method definition
- between method declarations
This is a weird question in that I'm not sure where to start looking.
First of all, I haven't done any C++ programming for the last 10 years so it could be me thats forgotten a few things. Secondly, the IDE I'm using is Eclipse based (which I've never used) and customized for Samsung bada based mobile development (it kicks off an emulator for debugging purposes)
I'm posting my code samples as images because the StackOverflow WYSIWYG editor seems to have a problem parsing C++.
[EDIT] Due to complaints I've edited my question to remove the images. Hope that helps :)
I have the following header file...
#include <FApp.h>
#include <FBase.h>
#include <FGraphics.h>
#include <FSystem.h>
#include <FMedia.h>
using namespace Osp::Media;
using namespace Osp::Graphics;
class NineAcross :
public Osp::App::Application,
public Osp::System::IScreenEventListener
{
public:
static Osp::App::Application* CreateInstance(void);
public:
NineAcross();
~NineAcross();
public:
bool OnAppInitializing(Osp::App::AppRegistry& appRegistry);
private:
Image *_problematicDecoder;
};
...and the following cpp file...
#include "NineAcross.h"
using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::System;
using namespace Osp::Graphics;
using namespace Osp::Media;
NineAcross::NineAcross()
{
}
NineAcross::~NineAcross()
{
}
Application* NineAcross::CreateInstance(void)
{
// Create the instance through the constructor.
return new NineAcross();
}
bool NineAcross::OnAppInitializing(AppRegistry& appRegistry)
{
Image *workingDecoder;
workingDecoder->Construct();
_problematicDecoder->Construct();
return true;
}
Now, in my cpp file, if I comment out the line that reads _problematicDecoder->Construct();...I'm able to set a breakpoint and happily step over the call to Constuct() on workingDecoder. However, as soon as I uncomment the line that reads _problematicDecoder->Construct();... I end up with the IDE telling me...
"No source available for "Osp::Media::Image::Construct()"
In other words, why can I NOT debug this code when I reference Image *image from a header file?
Any ideas?
Thanks :-)
This usually means you're stepping through some code which you do not posses its source.
I assume here that Osp::Media::Image is a class supplied by Samsung or similar for which you do not have the cpp file. So this means the debugger can't show you the current code line while you're at a function of Osp::Media::Image.
Alternatively, there's a good chance you do have all of the source code for this class, but Eclipse doesn't know where it is. In this case you can add the correct directories under the Debug Configurations window.
Ok, problem solved.
The idea is to first new up an instance of Image like so...
_decoder = new Osp::Media::Image();
And then do _decoder->Construct().
Funny enough, this seems blatantly obvious to me now coming from the C# world, though why the code I posted for workingDecoder works is still somewhat mysterious to me. The fact the sample projects pre-loaded with the bada IDE don't seem to make a call to new() leads me to believe that perhaps those samples are outdated our out of synch.
Either that or I really AM wildly out of the C++ loop.
Anyway thanks so much for the effort guys.
Appreciated :)