Invalid conversion from... Objective-C++ - casting

I just told Xcode to compile everything as Objective-C++ and now I have errors from casting.
void audioRouteChangeListenerCallback (
void *aInUserData,
AudioSessionPropertyID aInPropertyID,
UInt32 aInPropertyValueSize,
const void *aInPropertyValue
) {
// Ensure that this callback was invoked because of an audio route change
if (aInPropertyID != kAudioSessionProperty_AudioRouteChange) return;
// This callback, being outside the implementation block, needs a reference to the MixerHostAudio
// object, which it receives in the inUserData parameter. You provide this reference when
// registering this callback (see the call to AudioSessionAddPropertyListener).
TJUSimpleSequencer *lAudioObject = (TJUSimpleSequencer *) aInUserData;
// if application sound is not playing, there's nothing to do, so return.
if (NO == lAudioObject.isPlaying) {
NSLog (#"Audio route change while application audio is stopped.");
return;
} else {
// Determine the specific type of audio route change that occurred.
CFDictionaryRef routeChangeDictionary = aInPropertyValue; // !!! invalid conversion from 'const void*' to 'const __CFDictionary*'
CFNumberRef routeChangeReasonRef =
CFDictionaryGetValue (
routeChangeDictionary,
CFSTR (kAudioSession_AudioRouteChangeKey_Reason)
); // !!! invalid conversion from 'const void*' to 'const __CFNumber*'
When i try to use static_cast<CFDictionaryRef>(aInPropertyValue), I get nothing. As though (which is probably true) I am not using it correctly.

Use regular C cast?
CFDictionaryRef routeChangeDictionary = ( CFDictionaryRef )aInPropertyValue;
Edit 0:
How about this for that function call (if you're sure it's a number :)
CFNumberRef routeChangeReasonRef =
( CFNumberRef )CFDictionaryGetValue ( ...
Edit 1:
Take a look at The Definitive C++ Book Guide and List then.

Related

Use lambda function as microcontroller interrupts handler

For my microcontroller project I need custom timer with possibility to change interruption handler function. I created a Timer class for this.
I need to initialize ESP32 timer with function.
That is how I am trying to do this:
class Timer
{
private:
hw_timer_t* timer = nullptr;
std::function<void(void)>& onTimer;
public:
Timer(uint16_t intervalMs, std::function<void(void)>& newOnTimer): onTimer(newOnTimer)
{
timer = timerBegin(0, 40, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, intervalMs * 1000, true);
}
void start()
{
timerAlarmEnable(timer);
}
};
And timer initialization:
Timer t = Timer(250, []IRAM_ATTR(){
Serial.print("Tick ");
Serial.println(millis());
if(point)
{
point = false;
d.clearPixel(4, 4);
return;
}
point = true;
d.drawPixel(4,4);
});
But when I am launching it, I get:
sketch.ino: In constructor 'Timer::Timer(uint16_t, std::function<void()>&)':
sketch.ino:1161:35: error: cannot convert 'std::function<void()>*' to 'void (*)()'
timerAttachInterrupt(timer, &onTimer, true);
^~~~~~~~
In file included from /esp32/hardware/esp32/2.0.4/cores/esp32/esp32-hal.h:88,
from /esp32/hardware/esp32/2.0.4/cores/esp32/Arduino.h:36,
from sketch.ino.cpp:1:
/esp32/hardware/esp32/2.0.4/cores/esp32/esp32-hal-timer.h:39:53: note: initializing argument 2 of 'void timerAttachInterrupt(hw_timer_t*, void (*)(), bool)'
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
~~~~~~~^~~~~~~~~
sketch.ino: At global scope:
sketch.ino:1341:16: error: expected primary-expression before '(' token
Timer t = Timer(250, []IRAM_ATTR(){
^
In file included from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/hal/esp32/include/hal/cpu_ll.h:18,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/hal/include/hal/cpu_hal.h:16,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/esp_hw_support/include/esp_cpu.h:14,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/esp_hw_support/include/soc/cpu.h:14,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/esp_hw_support/include/soc/spinlock.h:11,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/freertos/port/xtensa/include/freertos/portmacro.h:42,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/freertos/include/freertos/portable.h:51,
from /esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/freertos/include/freertos/FreeRTOS.h:63,
from /esp32/hardware/esp32/2.0.4/cores/esp32/Arduino.h:33,
from sketch.ino.cpp:1:
sketch.ino: In lambda function:
/esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/esp_common/include/esp_attr.h:150:46: error: expected '{' before '__attribute__'
#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER))))
^~~~~~~~~~~~~
/esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/esp_common/include/esp_attr.h:23:19: note: in expansion of macro '_SECTION_ATTR_IMPL'
#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__)
^~~~~~~~~~~~~~~~~~
sketch.ino:1341:24: note: in expansion of macro 'IRAM_ATTR'
Timer t = Timer(250, []IRAM_ATTR(){
^~~~~~~~~
sketch.ino: At global scope:
sketch.ino:1341:24: error: expected ')' before '__attribute__'
Timer t = Timer(250, []IRAM_ATTR(){
~ ^
)
Error during build: exit status 1
I am not expert in C++, so I totally don't understand what I need to do there to fix it.
Could anyone who knows what to do tell me about this, please?
Thank you in advance.
The signature of timerAttachInterrupt is
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
Like the error says, you cannot convert a std::function<void()>* to a void(*)(). While std::function<...> is a class that can wrap pretty much any callable object and store the data needed (eg. the variables captured in a lambda), function pointers are just simple addresses in memory.
If your lambdas are simple and don't capture anything, like the one in your example, std::function is overkill. You can just use void(*)() instead and the issue is solved.
Otherwise, if your lambdas do capture stuff, then you need std::function and perhaps some static member variables.
Since you seem to be using only one timer, you could do something like this:
class Timer
{
private:
hw_timer_t* timer = nullptr;
static std::function<void(void)> onTimer;
static void onTimerCaller()
{
onTimer();
}
public:
Timer(uint16_t intervalMs, std::function<void(void)>&& newOnTimer)
{
if (onTimer)
{
// another Timer already exists. Show an error, somehow
}
onTimer = std::move(newOnTimer);
timer = timerBegin(0, 40, true);
timerAttachInterrupt(timer, &onTimerCaller, true);
timerAlarmWrite(timer, intervalMs * 1000, true);
}
void start()
{
timerAlarmEnable(timer);
}
};
The most important changes are1:
Add a onTimerCaller static function (that can be converted to void(*)() and therefore used with timerAttachInterrupt) which calls onTimer;
onTimer is now static, so it can be accessed from onTimerCaller.
Also note that I tried to keep the class as simple as possible. It should also have copy/move constructors/operators and a destructor. Additionally, there's not really much reason to even use a class in this case. A namespace with some functions would be simpler and cleaner.
It is also possible to support multiple timers, but I believe this may be enough for your use-case. Let me know if you'd like to see a version for multiple timers.
1 I also did some minor changes, like moving the std::function into the class to avoid a dangling reference.

Problem with creation of freeRTOS timer in ESP-IDF

I use ESP-IDF 4.2 and want to create a freeRTOS timer. My code is similar to what I have used successfully before but now I get a compilation error that I can't resolve. My code is based on the example in the ESP-IDF documentation on the xTimerCreate function. In the documentation an array of timers is created, whereas I want to create only one.
Here is my code:
void myTimerCallback(void){
std::cout << "test timer callback" << std::endl;
};
TimerHandle_t create_freeRTOSTimer(){
TimerHandle_t timerHandle;
int32_t Id = 0;
int durationTicks = 100;
timerHandle = xTimerCreate( "Timer", // Just a text name, not used by the kernel.
durationTicks, // The timer period in ticks.
pdTRUE, // The timer will auto-reload itself when it expires.
( void * ) Id, // unique id.
myTimerCallback // Callback when timer expires.
);
return timerHandle;
};
This is the compiler response:
error: invalid conversion from 'void ()()' to
'TimerCallbackFunction_t' {aka 'void ()(void*)'} [-fpermissive]
myTimerCallback // Each timer calls the same callback when it expires.
^~~~~~~~~~~~~~~ In file included from ../components/NiCMidi/src/../include/timer.h:46,
from ../components/NiCMidi/src/timer.cpp:26: C:/Users/Fred/esp-idf/components/freertos/include/freertos/timers.h:267:33:
note: initializing argument 5 of 'void* xTimerCreate(const char*,
TickType_t, UBaseType_t, void*, TimerCallbackFunction_t)'
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed
for strings and single characters only. */
For testing I replaced the myTimerCallback in the call of xTimerCreate by NULL. Then the compiler does not complain.
Oops, I forgot to use a parameter in the definition of the callback function!
When I use void myTimerCallback(TimerHandle_t pxTimer) for the definition, everything is OK!

callfunc in cocos2d-x

In cocos2d-x, the following piece of code is supposed to run the callback function after a delay. What do I need to do to fix the error?
bool LoadingLevelScreen::initialise() {
// set up the time delay
CCDelayTime *delayAction = CCDelayTime::actionWithDuration(0.5f);
// perform the selector call
CCCallFunc *callSelectorAction = CCCallFunc::actionWithTarget(
this, callfunc_selector( LoadingLevelScreen::menuCallbackStart ) );
// run the action
this->runAction( CCSequence::actions(
delayAction, callSelectorAction, NULL ) );
}
void LoadingLevelScreen::menuCallbackStart(CCObject * pSender)
{
}
Compiler Error:
error C2440: 'type cast' :
cannot convert from 'void (__thiscall LoadingLevelScreen::* )(cocos2d::CCObject *)'
to 'cocos2d::SEL_CallFunc'
Pointers to members have different representations; cannot cast between them
Either remove the CCObject* parameter in menuCallbackStart() method (because CCCallFunc::actionWithTarget() expects a method with no arguments), or change CCCallFunc to CCCallFuncO which expects a method with a CCObject* as argument, like so:
CCCallFuncO * callSelectorAction =
CCCallFuncO::create(this, &LoadingLevelScreen::menuCallbackStart, myObject);
where myObject is a CCObject * that will be passed to your method as the argument.
Note that callfunc_selector() is just a macro that typecasts your method to SEL_CallFunc:
#define callfunc_selector(MYSELECTOR) (SEL_CallFunc)(& (MYSELECTOR))
BTW ::actionWithTarget() is being deprecated, so use ::create() instead.
void LoadingLevelScreen::menuCallbackStart(CCObject * pSender)
{
}
should be
void LoadingLevelScreen::menuCallbackStart()
{
}
callfunc_selector is different with menu_selector, you don't need the CCObject* to pass in as a variable
if you do need to pass argument, please use callFuncND
this->runAction(Sequence::create(CallFunc::create(std::bind(&CNm::MNm, this)),NULL));
this->runAction(Sequence::create(CallFunc::create(std::bind(&ClassName::MethodName, this)),NULL));

C++ semantic issue, const value_type to pointer*

I'm trying to get this C++ method to return an array of b2Fixture instances. It iterates of a series of JRContact instances, which are defined like:
struct JRContact {
b2Fixture *fixtureA;
b2Fixture *fixtureB;
bool operator==(const JRContact& other) const
{
return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB);
}
};
n.b. I'm a total stranger to C++, don't hesitate to mention weird things I might have done in that code ;-)
The following fails to compile (XCode compiler on MacOS), see errors in comments:
id AbstractContactListener::getFixturesOfTypeCollidingWithFixture(b2Fixture *fix, int type){
std::vector<b2Fixture> fixtures;
std::vector<JRContact>::iterator ct;
JRContact contact;
for (ct = _contacts.begin(); ct != _contacts.end(); ct++){
contact = *ct;
if (
( (fix == contact.fixtureA) || (fix == contact.fixtureB) ) &&
( contactContainsType(contact, type) )
){
if (fix == contact.fixtureA) {
// error: Semantic Issue: Reference to type 'const value_type' (aka 'const b2Fixture') could not bind to an lvalue of type 'b2Fixture *'
fixtures.push_back(contact.fixtureB);
}
else {
// error: Semantic Issue: Reference to type 'const value_type' (aka 'const b2Fixture') could not bind to an lvalue of type 'b2Fixture *'
fixtures.push_back(contact.fixtureA);
}
}
}
// error: Semantic Issue: No viable conversion from 'std::vector<b2Fixture>' to 'id'
return fixtures;
}
Thanks for your time!
Change :
std::vector<b2Fixture> fixtures;
to :
std::vector<b2Fixture *> fixtures;
About the return type you can change it either to void* or std::vector<b2Fixture *> * and use : return &fixtures;
But pay attention the your vector is local so allocate it for not returning a pointer to an invalid location. (And ofcourse remember to free it when you done using it).
It's not really clear what you want to do, but the problem is you're telling the compiler that AbstractContactListener::getFixturesOfTypeCollidingWithFixture will return an id and you're instead returning an std::vector<b2Fixture>.
From the name of the function, I guess you might want to return a vector, so change the signature to:
std::vector<b2Fixture> AbstractContactListener::getFixturesOfTypeCollidingWithFixture
(b2Fixture *fix, int type)
You're also pushing pointers in your vector when you should be pushing objects:
fixtures.push_back(*(contact.fixtureB));
The vector fixtures holds b2Fixture instances, but the contact.fixtureA is a b2Fixture*.
Either:
dereference it:
fixtures.push_back(*(contact.fixtureA)); // Same for 'fixtureB'.
or,
change the type of fixtures:
std::vector<b2Fixture*> fixtures;
There is also a mismatch between the function return type and what is actually being returned. If you want to return fixtures, have the return type match the type of fixtures.

C++/SDL 'void*' is not a point-to-object type

I'm new on C++ and I'm trying to make some testing with C++ and SDL and in SDL we have a function:
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param);
which I can pass a callback for the timer created.
But apparently it converts my instance this to *void so I can't retrieve it again on the update method which is static, and it's interesting but the the SDL_AddTime doesn't work on a non static callback function.
Well, so my problem is that when trying to call the public method render through the void* param argument It complains about not being a pointer-to-object-type...
Is there any way I can get the Character instance again inside the update method since I don't have control over the SDL_AddTime function and I have to pass the required parameters?
Thanks
#include "Character.h"
Character::Character(void)
{
timer = SDL_AddTimer(33, update, this);
this->render(); // is called without problem
}
//static method
Uint32 Character::update(Uint32 interval,void* param)
{
param->render(); // yields: 'void*' is not a pointer-to-object type;
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.code = 1020;
event.user.data1 = param;
SDL_PushEvent(&event);
return interval;
}
void Character::render(void)
{
printf("rendering character \n");
}
You don't need a reinterpret_cast - a static_cast should be OK:
Character * cp = static_cast <Character *>( param );
You should avoid reinterpret_cast - it is almost always implementation specific, and may hide problems - just like old-style C casts.
Cast your param pointer to a Character:
Character * charPtr = reinterpret_cast<Character *>(param);
charPtr->render();
The reason is that C++ is a strong typed language. To change one type to another, you need to cast it first:
Uint32 Character::update(Uint32 interval, void* param)
{
reinterpret_cast<Character* >(param)->render();
/* ... */
}
Just for reference, if you were to call a lot of stuff in a function, to save all the nasty reinterpret_cast stuff everywhere you can do
Character * myCharacter = reinterpret_cast<Character* >(param);
Which then lets you do 'myCharacter->render();' or whathaveyou...