I'm updating my V1 cocos2d-x app to V3 and I'm stuck on callbacks.
I can do call backs with lambdas like this, works fine -
auto mcb = CallFunc::create([this](){
this->doCallback(kEVENT_MENU_IS_ONSCREEN);
});
hex->runAction(Sequence::create(somethingthattakestime, mcb, NULL) );
However, I want to pass a CallFunc variable into a function, store it in my object, then use/call it at some point in the future.
In a class I define -
CallFunc * callfunc;
Set with a simple -
item->callfunc = callfunc;
Within a function -
void LBMenuAddMenuItemName( CallFunc * callfunc );
I also declare the CallFunc variable as static so it hangs around -
static auto doSoloPlay = CallFunc::create([this](){
CCLOG("doSoloPlay variable");
this->menuSoloPlay();
});
Later when I wish to use this, I do -
Sequence * seq = Sequence::create(callfunc,NULL);
somesprite->runAction(seq);
However, this ends badly with a SIGSEGV (GLThread).
Using typeid(callfunc).name() shows that callfunc is a CallFunc. Using setTag(69) in declaration and then getTag() before SIGSEGV does not return a sensible value.
Can someone explain what I'm doing wrong and the correct method for delayed callbacks?
Thank you!
LB
Tried many things then found this error goes away when I do a 'retain()' after the declaration -
doSoloPlay->retain();
This increases the reference count.
I don't quite know why I need this. My guess is that cocos2d-x classes may do some clever garbage collection?
If the function is called later as a callback, you need to retain the callback when you save it and release it at the right time.
The static declaration only save the address of your CCCallFunc but the class is destroyed before you wish to execute it.
Related
I am creating a function in MATLAB that I want to export as a c++ library. The function takes in accelerometer and gyroscope data, and calculates orientation via imufilter. Here is how it works:
% when 10 samples come in, call below function
function [orientation] = runtime_get_orientation(accelerometer, gyro)
FUSE = imufilter('SampleRate', 50, 'AccelerometerNoise', 0.002, ...
'LinearAccelerationNoise', 0.003, ...
'GyroscopeNoise', 0.444, 'GyroscopeDriftNoise', 0.445);
[orientation,~] = FUSE(accelerometer, gyro);
end
Note: I am creating a realtime system which will call this function over time. Ex: 10 samples come in, and then I call this function. 10 more come in, and I call it again.
The problem I see is that the FUSE object state is re-set every time I make a call to the function. Meaning, the matrix that retain the error state over time and adjust to it, are wiped. If I pass the FUSE object to the function, as demonstrated below, the state is kept and I can view orientation that makes sense.
% define FUSE object outside of the function
FUSE = imufilter('SampleRate', 50, 'AccelerometerNoise', 0.002, ...
'LinearAccelerationNoise', 0.003, ...
'GyroscopeNoise', 0.444, 'GyroscopeDriftNoise', 0.445);
% when 10 samples come in, call below function
function [orientation] = runtime_get_orientation(accelerometer, gyro, FUSE)
[orientation,~] = FUSE(accelerometer, gyro);
end
I'd like to return the object state of the FUSE object back to the calling function, so that I can pass it as an argument back in. I expect that this is some sort of a matrix object. I want to do that because I will eventually want to export it as a c++ function, and exporting a FUSE object might not be possible from what I can tell.
What can I do to keep the state of the FUSE object, in a way that is codegen / c++ friendly?
One simple solution is to make the data a static variable in the function. That way, you can create the filter only the first time the function is called, and you don’t need to know about it outside of the function.
To declare a static variable in MATLAB, use the persistent keyword.
What I was doing before was that I was calling a function of my interface and it determinate in a switch condition thanks to a parameter what to do with the data. What kind of specialization they have.
But now, what I am trying to create a local object, treat it, and then add it to my containers of the interface.
In order to do that I have to copy all the value of my local object (which have been treated) in my container of the interface.
So I created a copy_cell function in the interface, a virtual one, and one in the subclass. But whenever I try to do it the interface function is called and not the subfunction.
GridCell_voxel * local_cell;
local_cell = new GridCell_voxel(m_grid_map( cell2matindex_x(cell_index_x), cell2matindex_y(cell_index_y))->getVoxelResolution(), m_grid_map( cell2matindex_x(cell_index_x), cell2matindex_y(cell_index_y))->getVoxel().size());
local_cell->process_points(relevant_points, m_mapping_type);
//This is the line I need to change
local_cell->copy_cell (m_grid_map( cell2matindex_x( cell_index_x), cell2matindex_y( cell_index_y))) ;
Do you have any idea on the way to go? What am I missing here?
Sorry for the lack of information, i will try to expose how i managed and what i was actually looking for.
So i have a container of IntefaceCell, called m_grid_map, full of cell that has been specialized. In my case m_grid_map is full of GridCell_voxel which is a sub class from InterfaceCell.
What i want to do is, create a new local GridCell_voxel, copy the information in it. Then process the informations, then copy the local cell in the container.
The important part is the dynamic_cast in the copy cell function, which allow you to take an InterfaceCell as argument and then treat it as GridCell_voxel.
//Main.cpp
GridCell_voxel * local_cell;
local_cell = new GridCell_voxel();
local_cell->copy_cell (m_grid_map( cell2matindex_x( cell_index_x), cell2matindex_y( cell_index_y)));
local_cell->process_points(relevant_points, m_mapping_type);
m_grid_map( cell2matindex_x( cell_index_x), cell2matindex_y( cell_index_y))->copy_cell (local_cell);
delete local_cell;
//GridCell_voxel.cpp
void GridCell_voxel::copy_cell(GridCellInterface* cell) {
GridCell_voxel* voxel_cell = dynamic_cast<GridCell_voxel*>(cell);
this->m_voxel_start_height = voxel_cell->m_voxel_start_height;
this->init = true;
this->m_ground_voxel_position = voxel_cell->m_ground_voxel_position;
}
I hope it will help someone.
I wanna to use NPAPI plugin in my app and i created a functions, provides by a browser to plugin. Load library, initialization and start, all goes well, until it comes to a function NPP_New. This function makes crash, because NPP pointer (tried instead to specify 0 - the function returns an error code 2 "Invalid Instance" and not crash). I think there is a problem in memory access.Found several ways of memory sharing, but I do not know exactly what is appropriate in this case.
// ...
char szMimeType[] = "application/x-some-plugin";
NPP_t npp; npp.pdata = 0; npp.ndata = &npp;
UINT result = NPP_New(szMimeType, &npp, NP_FULL, 0, 0, 0, NULL);
// ...
#Georg Fritzsche, you were right! The problem was in pointers to NPN_ functions. Variable NPNetscapeFuncs pNpnFuncs create and fill as a local in one of my functions and thus destroyed on completion of the function. When I did pNpnFuncs global variable - everything was fine work.
I'm essentially trying to delay a modification on an object by 10 seconds.
This is what I thought might work:
this->scheduleOnce(schedule_selector(customer->setBusy(false)), 10000);
But I get a compiler error:
Lvalue required as unary '&' operand
Is there a simple way to delay a line of code? Maybe just using a c++ command would be more efficient, but the sleep command is giving me issues as well.
You need to write you schedularOnce like this
In .h file you declare
void myModification(float dt);
In .cpp file
this->scheduleOnce(schedule_selector(&MyClass::myModification), 10.0f);
void Myclass::myModification(float dt)
{
//your code
}
ALL These are in cocos2d-x 2.2
You will need to make a function out of that single line of code because you can't pass values to a selector function. So something like this:
this->scheduleOnce(schedule_selector(MyClass::myModification), 10.0f);
Then you would have a function with the modification code in it.
void MyClass::myModification(float dt)
{
customer->setBusy(false);
// Whatever other stuff you want run.
}
Also, the delay at the end is measured in seconds, not milliseconds. So you would have been waiting a few hours for this to run.
You can also achieve this by creating a callback and calling it from within a sequence if your class derives from Node. This is a useful pattern if you need to create chains of actions or synchronize game events with action sequences. (Cocos version 3+)
const float myDelay = 1.0f;
this->runAction( Sequence::create(
DelayTime::create(myDelay),
CallFunc::create(CC_CALLBACK_0(MyClass::MyFunction, this)),
nullptr));
this->scheduleOnce it only can use itself method
I need to call a function of an object and pass it a variable. Because I need to make multiple call to function of this object I've tried to make one only handler that invoke the specific function by the form value I pass it. The code works, but CFBuilder show me that there is an error (missing semicolon on the last row). I'm on Railo.
local.myReport = seoUtility.init();
local.func = form.action;
local.report = local.myReport[local.func](form.user);
So the question is: this code is correct? I could simply ignore the cfbuilder error icon?
If you don't want CFBuilder to nag you about the syntax, you can change to this:
local.myReport = seoUtility.init();
local.func = local.myReport[form.action];
local.myReport.func = local.func;
local.report = local.myReport.func(form.user);
This sets local.func to the instance of seoUtility as a reference to the actual function you want to call, preserving its relationship to the parent object. This way the offending []() syntax isn't needed.
However, this only works if seoUtility.init() is returning a fresh instance every time, as opposed to a singleton shared by the application, in which case there would be a race condition on all calls to local.myReport.func().