[Maya C++ API] Unable to unload plugin in Maya
When developing a Maya plugin it can be very frustrating not to be able to unload a plugin because you have to restart Maya every time you want to test a change. Here are a few tips to help you pinpoint why you can't unload a Maya plugin.
The obvious
Unloading a plugin is done either by the unloadPlugin MEL command:
unloadPlugin plug_in_name;
or the GUI
Window -> Settings/Preferences -> Plug-in Manager
Remaining nodes or data in the Maya scene specific to your plugin, are typically the cause of why you may not be able to unload your Maya plugin.
Unlike the MEL command the GUI advantageously provide an error message with the list of nodes and data still in use. Either delete them manually in the Node editor or simply reset the scene using:
file -f -new;
I usually add a button in the shelf to quickly reset and unload the plugin at the same time.
Lastly there is the last resort unloadPlugin -force
flag which you should never use as stated here. The main reason being you will likely corrupt Maya memory context: Maya may crash or the next time you'll load your plugin it will produce erratic results and bugs that have nothing to do with your code (just restart Maya to clean up the memory).
The less obvious
A common mistake I do, is to forget to de-register a node or data I freshly implemented:
/// @brief first function executed by Maya when loading the plugin MStatus initializePlugin(MObject obj) { MFnPlugin plugin(obj, "", "1.0", "Any"); plugin.registerData("My_MPxData", ...); plugin.registerNode("My_MPxLocatorNode", ...); plugin.registerShape("My_MPxSurfaceShape", ...); return MS::kSuccess; } // ----------------------------------------------------------------------------- /// @brief last function executed by Maya when unloading the plugin MStatus uninitializePlugin(MObject obj) { MFnPlugin plugin(obj); // WARNING: it is important to deregister node/commands/data/... // in *reverse* order as they were registered. plugin.deregisterNode(My_MPxSurfaceShape::_id); plugin.deregisterNode(My_MPxLocatorNode::_id); plugin.deregisterData(My_MPxData::_id); return MS::kSuccess; }
You also have to respect the so called stack rule and be sure to de-register in reverse order registered nodes and data.
The last problem is harder to find, it happens when you extract the value of an MPxData
through an MPlug
.
MPlug plug(thisMObject(), _attribute_of_type_MPxData); MDataHandle handle; plug.getValue(handle); // Equivalent to: handle = plug.asMDataHandle(); // Do something with the handle. plug.destructHandle( handle ); // Don't forgot to destruct the handle! }
You must not forget to call MPlug::destructHandle()
or you could produce a memory leak. The effect would be to leave some MPxData
still in use preventing you to unload your plugin.
One comment
I got bit by the destructHandle thing. Thanks for this post!
Tyson - 12/07/2018 -- 22:36—————-
Rodolphe: Thanks! Always delighted to hear that I could be of help.