asio socket, inside a class declaration, scope issue - boost

I want to have a class inside which I initialize and open a tcp socket, but I want to repeatedly write to the socket only by calling a method of that class, without having to re-establish connection everytime.
My code is below. I get the compile time errors as pasted here below the code block.
The method is unable to see the socket that was initialized in the constructor. Seems to be a simple C++ "scope" issue, but beats me!
#include <ctime>
#include <iostream>
#include <string>
#include <asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using asio::ip::udp;
using asio::ip::tcp;
class rpcClass {
char sendBuffer[16];
asio::ip::tcp::endpoint epdPt;
asio::io_service io_service;
asio::ip::tcp::endpoint endPt;
public:
rpcClass () { // constructor
asio::ip::tcp::socket socketTCP(io_service);
strcpy (sendBuffer, "*Constructor*\n");
endPt = asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"),\
boost::lexical_cast<int>(5004));
socketTCP.connect(endPt);
socketTCP.write_some (asio::buffer(sendBuffer));
};
void sendRPCData (void) { //send data when called from main()
strcpy (sendBuffer, "rpcData\n");
socketTCP.write_some (asio::buffer(sendBuffer));
};
};
int main(void) {
rpcClass rpc; // I WANT THE rpc OBJECT TO SEND DATA
rpc.sendRPCData (); // ONLY WHEN THIS METHOD IS CALLED
return (0);
}
Here is the error output (Eclipse)
rpc-class.cpp: In member function ‘void rpcClass::sendRPCData()’:
rpc-class.cpp: error: ‘socketTCP’ was not declared in this scope
Thanks a lot for helping!
-pn

You've declared socketTCP as a local variable in the constructor, not a member variable of the class.
That means you can't use it in other functions.
Presumably you meant to declare a member variable, and initialize that in the constructor instead of a local variable.

Related

Why cant we delay initialise a class member with a non default constructor?

I have a class like below:
#pragma once
#include <atomic>
class MyClassAnother {
public:
MyClassAnother(int val) : m_val(val) {
}
private:
int m_val;
};
There is another class which holds an object to MyClassAnother
#pragma once
#include "MyClassAnother.hpp"
class MyClass {
public:
MyClass() {
}
void Func() {
anotherClassObject = MyClassAnother(2);
}
private:
MyClassAnother anotherClassObject;
};
And here is the main.cpp
#include "MyClass.hpp"
#include <iostream>
int main() {
MyClass object;
}
Of course the program does not compile. And its because of the following error
error: constructor for 'MyClass' must explicitly initialize the member
'anotherClassObject' which does not have a default
constructor
Question:
But why? Why can't I delay initialise the class member? Is the workaround to have a default constructor and delay initialise it with the real constructor later? Is it an anti pattern to do it this way then?
I know that this can be resolved by making MyClassAnother anotherClassObject a pointer. But I want to have MyClassAnother anotherClassObject as a member object or a reference member in this case.
The constructor must guarantee that all members are properly constructed and initialized, and this one doesn't do that. What happens if you forget to call Func() and then access objcect.anotherClassObject?
Delayed initialization in general could be considered an anti-pattern, and goes against the RAII idiom, which states that object construction should succeed if and only if initialization of underlying resources (MyClassAnother in this case) succeeded. It's a good pattern to follow, because it prevents having unusable objects around because they failed to initialize properly, or because somebody forgot to perform their delayed initialization steps.
If MyClass objects are actually usable without a MyClassAnother instance, you can wrap the latter in an std::unique_pointer (C++11) or an std::optional (C++17).
If MyClass objects are not usable without a MyClassAnother instance, you need to pass that instance to the constructor, or create it in the constructor's initializer list.

wxTimer not calling overriden Notify()

I'm running into an issue where I implemented a derived wxTimer class to override the Notify() call since I'm not using an owner implementation as described in the documentation.
When I debug the run, I can see
the timer is being instantiated
my_timer_instance->IsRunning() returns true
MyTimer::Notify() is never called
This leads me to believe that the timer is being set and running, but when it expires it's calling the base class Notify() procedure and not my override it's not calling notify() but I'm not sure why.
EDIT: I added frame->getTimer()->Notify(); to my app and the correct procedure was called. Therefore, the timer just isn't calling Notify when it expires.
EDIT2: Added this minimal working example, and the timer works as expected. I'll try to compare the two and see what the problem is.
MyApp.hpp
#pragma once
#ifndef __NONAME_H__
#define __NONAME_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/statusbr.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/frame.h>
#include <wx/timer.h>
///////////////////////////////////////////////////////////////////////////
class MyTimerClass : public wxTimer
{
wxFrame* MyFrame;
public:
MyTimerClass(wxFrame* frame): MyFrame(frame) {};
void Notify() override;
};
///////////////////////////////////////////////////////////////////////////////
/// Class MyFrame1
///////////////////////////////////////////////////////////////////////////////
class MyFrame1 : public wxFrame
{
private:
protected:
wxStatusBar* m_statusBar1;
MyTimerClass* MyTimer;
public:
void StartTimer(int TimeInSeconds);
MyFrame1(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(500, 300), long style = wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL);
~MyFrame1();
};
#endif //__NONAME_H__
MyApp.cpp
#include "MyApp.hpp"
#include "wx/wxprec.h"
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
///////////////////////////////////////////////////////////////////////////
void MyTimerClass::Notify()
{
MyFrame->SetStatusText("Timer popped", 0);
}
MyFrame1::MyFrame1(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(parent, id, title, pos, size, style)
{
MyTimer = new MyTimerClass(this);
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
m_statusBar1 = this->CreateStatusBar(1, wxSTB_SIZEGRIP, wxID_ANY);
this->Centre(wxBOTH);
this->StartTimer(5);
}
void MyFrame1::StartTimer(int TimeInSeconds)
{
SetStatusText("Timer started with " + std::to_string(TimeInSeconds) + " seconds.");
MyTimer->Start(TimeInSeconds * 1000);
}
MyFrame1::~MyFrame1()
{
}
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon (under Windows it is in resources and even
// though we could still include the XPM here it would be unused)
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
class MyApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE;
};
enum
{
// menu items
Minimal_Quit = wxID_EXIT,
Minimal_About = wxID_ABOUT
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
// call the base class initialization method, currently it only parses a
// few common command-line options but it could be do more in the future
if (!wxApp::OnInit())
return false;
// create the main application window
MyFrame1 *frame = new MyFrame1(NULL, -1, "Test Frame");
frame->Show(true);
return true;
}
#BobbyTables,
From the documentation:
This member should be overridden by the user if the default
constructor was used and SetOwner() wasn't called.
Is it the case?
Nothing seems to be wrong in the code you show (although I'd change a few things, such as using raw pointer for my_timer_instance), so the problem must be elsewhere. As usual, the best would be to come up with a SSCCE, without it I can only offer some guesses as to what the problem actually is.
Are you running the event loop? The timers will only fire when it's running, so if you block doing some computation, this wouldn't happen.
Also, what is frame in Notify()? Is this a global (I'd rather pass it as parameter to MyTimer ctor)?
So after mimicking the code provided in the question, the following changes were made:
Instead of using a getter and setter to access the private timer member, I instead use
void refreshTimer(int time_in_seconds) in my parent frame class and create the timer in the parent frame's constructor rather than letting the app create it and pass it in.
I don't see why either of those two things would change the behavior of the timer but the timer now works as expected. I apologize for not being able to identify a concrete bug as the source of the problem.
NOTE: This behavior was caused by the timer being invoked outside the wxwindow's thread. Be careful when creating multithreaded programs using wxwidgets as a GUI. To circumvent this issue since I needed the timer to be invoked in a different thread, I created my own timer class that works correctly.

Callback pattern with a Functor

I'm trying to wrap an HttpRequest object (from Cocos2d-x) in my own functor. Everything's working fine except calling the callback passed to my functor. Can you spot the error in the classes below? (I only pasted the relevant parts of the code).
Cloud.hpp:
#ifndef Cloud_hpp
#define Cloud_hpp
#include "external/json/document.h"
#include "network/HttpClient.h"
using namespace cocos2d::network;
typedef std::function<void()> CloudCallback;
class Cloud
{
private:
std::string url { "http://localhost:3000/1.0/" };
std::string end_point;
CloudCallback callback;
std::string getPath();
void onHttpRequestCompleted(HttpClient *sender, HttpResponse *response);
public:
Cloud (std::string end_point) : end_point(end_point) {}
void operator() (CloudCallback callback);
};
#endif /* Cloud_hpp */
This is the class that stores the callback passed in the constructor. Here's the implementation:
#include "Cloud.hpp"
#include <iostream>
std::string Cloud::getPath()
{
return url + end_point;
}
void Cloud::operator()(CloudCallback callback)
{
this->callback = callback;
std::vector<std::string> headers;
HttpRequest* request = new (std::nothrow) HttpRequest();
request->setUrl(this->getPath().c_str());
request->setRequestType(HttpRequest::Type::GET);
request->setHeaders(headers);
request->setResponseCallback(CC_CALLBACK_2(Cloud::onHttpRequestCompleted, this));
HttpClient::getInstance()->send(request);
request->release();
}
void Cloud::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
{
this->callback();
}
What I'm trying to do is, make a simple Http request with the help of a functor, calling like this:
Cloud cloud("decks");
cloud([&]() {
CCLOG("Got the decks");
});
I'm getting EXC_BAD_ACCESS(Code=EXC_I386_GPFLT) as soon as the line
this->callback();
is called.
What is it that I am doing wrong here?
EDIT: Now I guess it's something to do with threads. If I remove the HttpRequest and call the callback method passed to the operator() immediately, this works without any problems. Begging for help :-)
It looks like the problem could be a lifetime issue. Since the http response callback is called asynchronously, some objects may have been destroyed in the meantime. There are two possibilities:
The Cloud object itself is destroyed before the callback is called.
One or more objects referenced by the lambda (since you're capturing by reference), may have also gone out of scope and been destroyed.
Try this:
void Cloud::operator()(const CloudCallback &callback)

Subscriber error in ROS

This is my subscriber declaration followed by the callback function
message_filters::Subscriber<geometry_msgs::Point32>
point_sub(*nh, "tracked_point", 1);
point_sub.registerCallback(&visualservoing3D::pointCallback);
The callback declaration is
void
visualservoing3D::pointCallback(const geometry_msgs::Point32ConstPtr& msg)
{
//Some functions
}
But the following error pops up. I know its something to do with my subscriber.
/usr/include/boost/function/function_template.hpp:225:
error: no match for call to
‘(boost::_mfi::mf1<void,
visualservoing3D, const
boost::shared_ptr<const
geometry_msgs::Point32_<std::allocator<void>
> >&>) (const boost::shared_ptr<const geometry_msgs::Point32_<std::allocator<void>
>&)’
Thanks,
Nagsaver
point_sub.registerCallback(&visualservoing3D::pointCallback);
You need to bind the non-static member function to an object instance:
#include <boost/bind.hpp>
point_sub.registerCallback(boost::bind(&visualservoing3D::pointCallback, p_vs, _1));
Where p_vs is a (shared) pointer to a visualservoing3D object. If you need/wish to bind to a reference, use boost::ref(vs)

Error "C3145" and "C2061" in C++ Visual Studio

EDIT: What is C++/CLI? I am programming in Visual studio, and as far as I know using C++... Also, The first error was solved by Peter's comment, but I am still stuck on the second.
I am brand new to the world of C++, and have previously done all my work in Java. I am unfamiliar with the use of pointers and garbage collection (though I believe I understand the concept) and I believe that may be the source of my problems. I am getting the following error messages:
1>Runner.cpp(6): error C3145: 'formOutOfTime' : global or static variable may not have managed type 'System::Windows::Forms::Form ^'
1> may not declare a global or static variable, or a member of a native type that refers to objects in the gc heap
1>Runner.cpp(22): error C2061: syntax error : identifier 'FormOutOfTime'
My code is like this:
PurpleHealth.cpp (This is the file I believe the system calls to start it all off):
#include "FormOutOfTime.h"
#include "FormParentalOverride.h"
#include "Runner.h"
using namespace PurpleHealth;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
//Application::Run(gcnew FormOutOfTime());
Runner* runner = new Runner();
//delete runner;
return 0;
}
Runner.h (this is the header file I want to run all my main code, and launch the forms. I also struggle with the purpose behind the header files)
#include "stdafx.h"
#include "FormOutOfTime.h"
#include "FormParentalOverride.h"
class Runner
{
public:
Runner();
~Runner();
// functions
private:
void Go();
// member variables
};
And Finally Runner.cpp:
#include "stdafx.h"
#include "Runner.h"
#include "FormOutOfTime.h"
#include "FormParentalOverride.h"
//Variable Dclaration
System::Windows::Forms::Form^ formOutOfTime;//Error Here***************************
Runner::Runner()
{
// Do stuff if you need to
this->Go();
}
Runner::~Runner()
{
// Clear memory if you need to
}
void Runner::Go()
{
formOutOfTime = gcnew FormOutOfTime();//Error Here***************************
formOutOfTime->ShowDialog();
}
Please help me solve these messages, and even critique on form is appreciated. Thanks.
managed pointers cannot be declared at static or global scope. They can only be declared at function scope. Move the declaration of formOutOfTime from the top of the runner.cpp file to within the Go method

Resources