I wanted to remove file when the program is closed, but not ended. I tried to do it with function std::atexit, but its parameter can't be pointer to a function if that's class member function. So I was wondering is there any simple alternative?
class User
{
std::experimental::filesystem::path file_path;
std::experimental::filesystem::path & get_file_path();
void clean_file_path();
void (User::*x)();
}
int main()
{
std::experimental::filesystem::path p = user.get_file_path();
user.x = & User::clean_file_path;
std::ofstream output(p, std::ios::binary | std::ios::trunc);
std::atexit(user.x);
}
You could have a static function inside your class and you could call "atexit" with a pointer to this static function:
class User
{
public:
void clean();
static void cleanStatic();
};
int main()
{
void (User:: * pClean)() = &User::clean;
void (*pCleanStatic)() = &User::cleanStatic;
std::atexit(pCleanStatic);
}
You can register multiple functions with "atexit" but there is a limit to that number so maybe registering only one function that will handle the work for all the objects is a better solution.
One more thing: the type of pCleanStatic and the type of pClean are not the same:
pCleanStatic is void(*)()
pClean is void(User::*)()
"atexit" expects a parameter of type void(*)(). So only pCleanStatic will be accepted as a parameter. In Visual Studio, if you try to compile the code
std::atexit(pClean);
you'll get the following error:
error C2664: 'int atexit(void (__cdecl *)(void))': cannot convert argument 1 from 'void (__thiscall User::* )(void)' to 'void (__cdecl *)(void)'
mentioning the two different types.
Related
I have a C++ codebase that I'm exposing to R using Rcpp modules. Specifically, I use an interface pattern where the class(es) I expose is actually an abstraction layer on top of the underlying object, which is the implementation.
The class(es) I'm dealing with also interact with each other, and have methods that take as arguments shared pointers to objects. I'm having trouble figuring out the right way to expose these methods to R.
Eg here is some code. The TestClass::combine method takes a pointer to another TestClass object and does stuff with it. When I try to compile this code, I get compiler errors (see below) when I add the corresponding interface method ITestClass::combine to the module.
Implementation:
class TestClass
{
public:
TestClass(int const& n, double const& x)
: n(n), x(x)
{}
const double get_x() {
return x;
}
double combine(std::shared_ptr<TestClass> obj) {
return x + obj->get_x();
}
protected:
int n;
double x;
};
Interface:
//' #export ITestClass
class ITestClass
{
public:
ITestClass(int const& in_n, double const& in_x)
: impl(in_n, in_x)
{}
double get_x() {
return impl.get_x();
}
double combine(ITestClass obj) {
return impl.combine(obj.get_object_ptr());
}
std::shared_ptr<TestClass> get_object_ptr() {
std::shared_ptr<TestClass> ptr(&impl);
return ptr;
}
private:
TestClass impl;
};
RCPP_MODULE(RTestClassModule)
{
class_<ITestClass>("ITestClass")
.constructor<int, double>()
.method("get_x", &ITestClass::get_x, "get_x")
.method("combine", &ITestClass::combine, "combine"); // this line errors out
}
A sample of the errors I get:
In file included from C:/Rlib/Rcpp/include/Rcpp/as.h:25,
from C:/Rlib/Rcpp/include/RcppCommon.h:168,
from C:/Rlib/Rcpp/include/Rcpp.h:27,
from interface1.cpp:2:
C:/Rlib/Rcpp/include/Rcpp/internal/Exporter.h: In instantiation of 'Rcpp::traits::Exporter<T>::Exporter(SEXP) [with T = testpkg::ITestClass; SEXP = SEXPREC*]':
C:/Rlib/Rcpp/include/Rcpp/as.h:87:41: required from 'T Rcpp::internal::as(SEXP, Rcpp::traits::r_type_generic_tag) [with T = testpkg::ITestClass; SEXP = SEXPREC*]'
C:/Rlib/Rcpp/include/Rcpp/as.h:152:31: required from 'T Rcpp::as(SEXP) [with T = testpkg::ITestClass; SEXP = SEXPREC*]'
C:/Rlib/Rcpp/include/Rcpp/InputParameter.h:34:43: required from 'Rcpp::InputParameter<T>::operator T() [with T = testpkg::ITestClass]'
C:/Rlib/Rcpp/include/Rcpp/module/Module_generated_CppMethod.h:111:69: required from 'SEXPREC* Rcpp::CppMethod1<Class, RESULT_TYPE, U0>::operator()(Class*, SEXPREC**) [with Class = testpkg::ITestClass; RESULT_TYPE = double; U0 = testpkg::ITestClass; SEXP = SEXPREC*]'
C:/Rlib/Rcpp/include/Rcpp/module/Module_generated_CppMethod.h:109:10: required from here
C:/Rlib/Rcpp/include/Rcpp/internal/Exporter.h:31:31: error: no matching function for
call to 'testpkg::ITestClass::ITestClass(SEXPREC*&)'
Exporter( SEXP x ) : t(x){}
^
interface1.cpp:17:5: note: candidate: 'testpkg::ITestClass::ITestClass(SEXP, const int&, const double&)'
ITestClass(SEXP in_date, int const& in_n, double const& in_x)
^~~~~~~~~~
interface1.cpp:17:5: note: candidate expects 3 arguments, 1 provided
interface1.cpp:14:7: note: candidate: 'constexpr testpkg::ITestClass::ITestClass(const testpkg::ITestClass&)'
class ITestClass
^~~~~~~~~~
interface1.cpp:14:7: note: no known conversion for argument 1 from 'SEXP' {aka 'SEXPREC*'} to 'const testpkg::ITestClass&'
interface1.cpp:14:7: note: candidate: 'constexpr testpkg::ITestClass::ITestClass(testpkg::ITestClass&&)'
interface1.cpp:14:7: note: no known conversion for argument 1 from 'SEXP' {aka 'SEXPREC*'} to 'testpkg::ITestClass&&'
How do I define ITestClass::combine so that it can be called from R?
I found a better solution, one that has the preferred interface for combine and doesn't seem to run into problems with garbage collection.
A couple of points:
Because the underlying API works extensively with shared pointers, rather than storing a TestClass object in impl, I store a std::shared_ptr<TestClass>. This is referenced directly, rather than creating new shared ptrs from scratch (which crash R when they get destroyed).
I leverage the internal structure of the returned refclass object from an Rcpp module. In particular, it has a .pointer member that is a pointer to the underlying C++ object. So I can dereference that to get the impl member.
New interface:
//' #export ITestClass2
class ITestClass2
{
public:
ITestClass2(int const& in_n, double const& in_x)
: impl(in_n, in_x))
{}
double get_x()
{
return impl->get_x();
}
double combine(Environment obj)
{
SEXP objptr = obj[".pointer"];
ITestClass2* ptr = (ITestClass2*) R_ExternalPtrAddr(objptr);
return impl->combine(ptr->get_object_ptr());
}
// this doesn't need to be seen from R
protected:
std::shared_ptr<TestClass> get_object_ptr()
{
return impl;
}
private:
std::shared_ptr<TestClass> impl;
};
RCPP_MODULE(RTestClassModule2)
{
class_<ITestClass2>("ITestClass2")
.constructor<int, double>()
.method("get_x", &ITestClass2::get_x, "get_x")
.method("combine", &ITestClass2::combine, "combine")
;
}
Call this in R as follows:
obj <- new(ITestClass2, 1, pi)
obj2 <- new(ITestClass2, 2, exp(1))
obj$combine(obj2)
Edit: see better answer here
I found a rather kludgy solution that involves calling the R foreign language API directly:
class ITestClass {
...
double combine(SEXP obj) {
TestClass* ptr = (TestClass*) R_ExternalPtrAddr(obj);
std::shared_ptr<TestClass> sptr(ptr);
return impl.combine(sptr);
}
Rcpp::XPtr<TestClass> get_object() {
return Rcpp::XPtr<TestClass>(&impl);
}
}
obj1 <- new(ITestClass, 1, pi)
obj2 <- new(ITestClass, 2, -0.1)
obj1$combine(obj2$get_object())
# [1] 3.041593
This isn't great for a couple of reasons:
On the R side, I have to pass obj$get_object() as the argument to combine, which is highly non-intuitive
I've seen answers noting that Rcpp::XPtr and std::shared_ptr don't work well together, since they both try to manage the memory pointed to
Hopefully there's a better solution out there.
I have this base class:
// put the display in a macro on a .h file for less headache.
class Gadget {
protected:
int x, y;
U8GLIB * u8g;
virtual int f_focus() {return 0;};
virtual int f_blur() {return 0;};
virtual void f_draw() {};
virtual void f_select() {};
public:
Gadget(U8GLIB * u8g, int x, int y) :
u8g(u8g),
x(x),
y(y)
{
Serial.println(F("Gadget(U8GLIB * u8g, int x, int y)"));
};
Gadget() {
Serial.println(F("Gadget()"));
};
int focus(){return f_focus();};
int blur(){return f_blur();};
void draw(){f_draw();};
void operator()(){f_select();};
};
And this derived class:
class WakeUp :
public Gadget
{
public:
WakeUp(U8GLIB * u8g) :
Gadget(u8g, 0, 0)
{
Serial.println(F("WakeUp(U8GLIB * u8g)"));
};
};
Then I instantiate the WakeUp class inside an array like this:
Gadget gadgets[1] = {
WakeUp(&u8g)
};
Then I try to access this member like this:
void focus() {
Serial.println(gadgets[0].focus());
}
It is supposed to display 0. However it is displaying -64. Even if I override the f_focus() method on WakeUp class. If I remove the virtual specifier from f_focus() it works fine, displaying 0, but I will not be able to access the derived class implementation of this method.
I wish to understand what is causing this strange behavior and what can I do to avoid it.
EDIT:
The function runs fine if I call it from the Gadget Constructor.
You're slicing your WakeUp object.
You essentially have the following:
Gadget g = WakeUp(...);
What this code does is the following:
Construct a WakeUp object.
Call Gadget(const Gadget& other) with the base from the WakeUp object.
Destroy the temporary WakeUp object, leaving only the copy of the Gadget base.
In order to avoid this, you need to create an array of pointers (this is better if they are smart pointers).
Gadget* gadgets[1] = { new WakeUp(&u8g) }; // If you choose this method, you need to call
// delete gadget[0] or you will leak memory.
Using a pointer will correctly preserve the Gadget and WakeUp instances instead of slicing them away.
With smart pointers:
std::shared_ptr<Gadget> gadgets[1] = { std::make_shared<WakeUp>(&u8g) };
I am not able to call negedge of all the subscribers who register for clock, all subscribers also derive from ClkIf
class ClkAdapter : public ClkIf
{
virtual void negedge()
{
for(std::list<ClkIf*>::iterator it = clk_list.begin(); it != clk_list.end(); it++)
(it->negedge)();
}
virtual void posedge()
{ clk_cnt++; }
void registerForClock(ClkIf* module)
{ clk_list.push_back(module); }
std::list<ClkIf*> clk_list;
unsigned long long clk_cnt;
};
error: request for member 'negedge' in '* it.std::_List_iterator<_Tp>::operator-> with _Tp = ClkIf*', which is of non-class type 'ClkIf*'
Error in negedge function, What is wrong in this code??
You have a list of pointers, so the list iterator would work similarly to a double pointer (that is, ClkIf**). Thus, you would have to call (*it)->negedge() within the loop. The (*it) fetchs the current ClkIf* element first, and then the -> operator calls the function on that value.
I'm trying to hack with Qt's signals and slots, and I ran into an issue where QMetaType::invokeMethod won't properly pass pointer arguments to the slot being called.
call(QObject *receiver, const char *slot, const QList<QGenericArgument> &args)
{
const QMetaObject *meta = receiver->metaObject();
bool success = meta->invokeMethod(receiver, slot,
args.value(0, QGenericArgument()),
args.value(1, QGenericArgument()),
args.value(2, QGenericArgument()),
...
args.value(9, QGenericArgument()));
}
Then I call it the following way:
MyReceiver *receiver;
MyObject *myObject;
call(receiver, "mySlot", QList<QGenericArgument>() << Q_ARG(MyObject *, myObject));
Where class MyObject : public QObject { ... }. I also do Q_DECLARE_METATYPE(MyObject *) and qRegisterMetaType<MyObject *>("MyObject *")
What happens is that the slot on the receiver is being invoked, but with the value of the argument is always 0 no matter what I pass to the call(...) as Q_ARG
Out of curiosity I looked into the auto-generated MOC file of the receiver, and found that the slots are invoked with the following code:
void MyReceiver::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
Q_ASSERT(staticMetaObject.cast(_o));
MyReceiver *_t = static_cast<MyReceiver *>(_o);
switch (_id) {
case 0: _t->mySlot((*reinterpret_cast< MyObject*(*)>(_a[1]))); break;
default: ;
}
}
}
Turns out that the value of _a[1] bears proper address of MyObject *. But the reinterpret_cast turns it into 0.
Now I have the following questions:
1) How to programmatically invoke a slot and make sure that the pointer arguments are properly passed to the slot?
2) What does this *reinterpret_cast< MyObject*(*)>(_a[1]) mean? What the extra parentheses (*) mean, and how to interpret this piece of code?
Ok, I think I figured why it's not working... Q_ARG only will create a pointer to my pointer and store the former. I didn't mention that the call function was part of the Task call meant to invoke a slot later on - when the values wrapped into Q_ARG are already out of scope. Basically Q_ARG only maintains a weak reference to the argument object.
please help me out , why my code cannot compile,
the compiler complains that:
error C2629: 意外的“StringToAnsi (”
error C2334: “{”的前面有意外标记;跳过明显的函数体
error C2629: 意外的“StringToAnsi (”
...
Here is my code:
#using <System.dll>
#using <mscorlib.dll>
class StringToAnsi
{
private:
void * m_ptr;
public:
StringToAnsi( System::Object ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(safe_cast<System::String^>(str)).ToPointer();
}
StringToAnsi(System::String ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str).ToPointer();
}
~StringToAnsi()
{
System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr(m_ptr));
}
operator const ACHAR*()
{
return (const ACHAR*)m_ptr;
}
Because you have two constructors with the same number of parameters. There is an Object and a String, but both are an Object. So this seems very ambiguous.
When you create two methods (or constructors), you can't let them have the same number of parameters, because the compiler doesn't know which one to call.
When you put in a string into the construction like so: new StringToAnsi("bla"). The compiler doesn't know which constructor to use.