Create a pointer to a MFnMesh - c++

I am trying to create function that receive a MFnMesh pointer and do things on it.
The problem is that I cannot convert my MFnMesh to a pointer, I think the problem is not only on this class but on MFnBaseClass because I get this error.
/usr/autodesk/maya2015-x64/include/maya/MFnBase.h:168:14: error: ‘MFnMesh* MFnMesh::operator&() const’ is private
MFnClass * operator& () const
^
/usr/autodesk/maya2015-x64/include/maya/MFnDagNode.h:237:2: note: in expansion of macro ‘declareMinimalMFn’
declareMinimalMFn( MFnClass ); \
^
/usr/autodesk/maya2015-x64/include/maya/MFnMesh.h:243:2: note: in expansion of macro ‘declareDagMFn’
declareDagMFn(MFnMesh, MFnDagNode);
^
/home/k.masson/Documents/maya/km_extendedColorSet/src/km_particlesToColorSet.cpp:159:9: error: within this context
test(&meshFn);
^
Here is the function test which is in somefile.h and included in the file which call the function.
void test(MFnMesh * meshFn){
MStatus status = MS::kSuccess;
MString csName("YOLOSWAQDAZD");
status = meshFn->createColorSetDataMesh(csName);
MCheckStatus(status,"Error creating new color set");
}
And here is what I do before calling the test function.
// Get the out mesh data
MDataHandle outMeshHandle = data.outputValue(aOutGeometry, &status);
MCheckStatus(status,"ERROR getting aOutGeometry");
// Copy the in mesh to the output
outMeshHandle.copy(inMeshData);
// Create a function set for the out mesh
MFnMesh meshFn(outMeshHandle.asMesh());
test(&meshFn);
I didn't found any way to convert my MFnMesh to a pointer so I tried to directly call it as an object and not a pointer like this.
test(meshFn);
void test(MFnMesh meshFn){
MStatus status = MS::kSuccess;
MString csName("YOLOSWAQDAZD");
status = meshFn.createColorSetDataMesh(csName);
MCheckStatus(status,"Error creating new color set");
}
And I get this :
/usr/autodesk/maya2015-x64/include/maya/MFnMesh.h:243:16: error: ‘MFnMesh::MFnMesh(const MFnMesh&)’ is private
declareDagMFn(MFnMesh, MFnDagNode);
^
/usr/autodesk/maya2015-x64/include/maya/MFnBase.h:166:9: note: in definition of macro ‘declareMinimalMFn’
MFnClass( const MFnClass &rhs ); \
^
/usr/autodesk/maya2015-x64/include/maya/MFnMesh.h:243:2: note: in expansion of macro ‘declareDagMFn’
declareDagMFn(MFnMesh, MFnDagNode);
^
/home/k.masson/Documents/maya/km_extendedColorSet/src/km_particlesToColorSet.cpp:159:14: error: within this context
test(meshFn);
^
In file included from /home/k.masson/Documents/maya/km_extendedColorSet/src/km_particlesToColorSet.cpp:29:0:
/home/k.masson/Documents/maya/km_extendedColorSet/src/kmColorSetTool.h:29:6: error: initializing argument 1 of ‘void test(MFnMesh)’
void test(MFnMesh meshFn){
So do you know if there is anyway to create a function that acts on a MFnBase class in a fashion way, or even a class with a MFnBase attribute ? I don't know we can't do this kind of process which is really current..
I am new to c++ so it may be possible that I did a dumb mistake.

The MFnBaseClass does not allow to use the conversion to a pointer, instead, use a reference which works almost the same. See References vs. Pointers for more information.
The correct signature for my function is
void test(MFnMesh& meshFn)
And the way to use it is
test(meshFn);
And to use the reference in the function, just use it as a regular object
void test(MFnMesh& meshFn){
MStatus status = MS::kSuccess;
MString csName("YOLOSWAQDAZD");
status = meshFn.createColorSetDataMesh(csName);
MCheckStatus(status,"Error creating new color set");
}

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.

No Matching function to call C++

I have 2 classes TreeManager and TreeProducerBase. I am getting an error in passing an object of TTree( which is a class to make trees) to a function in TreeProducerBase from TreeManagerconstructor.
Note : I have defined tree as
TTree *tree_
Function call :
tpb.initialize(&tree_);
Here, tpb is an object of TreeproducerBase class.
This is the function that is being called.
void initialize(TTree &tree_)
It shows the error as follows:
error: no matching function for call to 'TreeProducerBase::initialize(TTree*&)'
Where am I doing wrong?
You are trying to pass pointer-to-pointer-to-TTree to a function that expects reference-to-TTree. Try redeclare it like
void initialize(TTree* &tree_);
Invokation will look like
tpb.initialize(tree_);
And then you can initialize outer pointer via simple assignment:
void initialize(TTree* &tree_) {
tree_ = new TTree(); // or smth else
}

Redirecting stdout to LCD: pointer of member class

FILE *LCD_stdout = new FILE();
int (*ptr)(char, FILE *) = ROBOT::__LCD_putchar;
fdev_setup_stream(LCD_stdout, ptr, NULL, _FDEV_SETUP_WRITE );
stdout = LCD_stdout;
gives me error:
In member function 'SUBSYS_OPENSTAT ROBOT::LCD_open()':
LCD.cpp:108: error: argument of type 'int (ROBOT::)(char, __file*)' does not match 'int (*)(char, __file*)'
I've looked at a number of solutions through Stack Overflow and whatnot. .* doesn't resolve it, tried assigning a pointer of a pointer, and I feel I'm likely not going to be resolve it without resolving misconceptions.
The compiler error tells you exactly what's wrong:
argument of type 'int (ROBOT::)(char, __file*)' does not match 'int (*)(char, __file*)
...because pointers to member functions aren't compatible with pointers to non-member functions, for a couple of reasons.
One option is to create a separate free function but this depends on where the ROBOT object resides. For example if you have a global ROBOT object you could do the following
ROBOT globalRobot;
int callback(char c, FILE* f)
{
return globalRobot.__LCD_putchar(c, f);
}
FILE *LCD_stdout = new FILE();
fdev_setup_stream(LCD_stdout, callback, NULL, _FDEV_SETUP_WRITE );
stdout = LCD_stdout;
If there is only going to be one robot object and it is a member variable of another class change globalRobot to be a pointer and set it after the ROBOT object has been created (ROBOT's constructor maybe)
This is untested as I don't know the innards of ROBOT but everything looks 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));

Invalid conversion from... Objective-C++

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.