Some background, when loading a .py file with my AutoCAD plugin, the file is parsed and register commansd in AutoCAD
Users can call newly created commands at the command line.
as sample .py might look like:
import wx
from wx import xrc
import PyRxApp# = all the global methods like acutPrintf,
import PyRx# = Runtime runtime
import PyGe# = Geometry
import PyGi# = Graphics interface
import PyDb# = database
import PyAp# = application, document classes services
import PyEd# = editor
def OnPyInitApp():
print("\nOnPyInitApp")
def OnPyUnloadApp():
print("\nOnPyUnloadApp")
def OnPyLoadDwg():
print("\nOnPyLoadDwg")
def OnPyUnloadDwg():
print("\nOnPyUnloadDwg")
#command to launch the dialog
def PyRxCmd_wxpyxrc():
try:
dlg = TestDialog(None, -1, "")
if dlg.ShowModal() == wx.ID_OK:
print('woohoo')
except Exception as err:
print(err)
finally:
# explicitly cause the dialog to destroy itself
dlg.Destroy()
class TestDialog(wx.Dialog):
def __init__(
self, parent, id, title, size=wx.DefaultSize, pos=wx.DefaultPosition,
style=wx.DEFAULT_DIALOG_STYLE, name='DlgTable'):
wx.Dialog.__init__(self)
self.res = xrc.XmlResource('C:/Users/Dan/Documents/DialogBlocks Projects/table dlg/wxg_dlg_inserttable.xrc')
self.res.LoadDialog(self, parent, "DLG_INSERTTABLE")
where ever my plugin calls into python, I’ve added a class WxPyAutoLock, just matching wxPyBeginBlockThreads / wxPyEndBlockThreads
the C++ side looks like:
static void AcRxPyApp_pyfunc(void)
{
if (curDoc() != nullptr)
{
const AcString cmdName = commandForCurDocument();
if (PyRxApp::instance().commands.contains(cmdName))
{
try
{
PyObject* method = PyRxApp::instance().commands.at(cmdName);
if (method != nullptr)
{
WxPyAutoLock lock;
PyErr_Clear();
if (PyCallable_Check(method))
{
PyObjectPtr rslt(PyObject_CallFunction(method, NULL));
if (rslt != nullptr)
return;
}
}
}
catch (...)
{
acutPrintf(_T("\npyfunc failed with exception: "));
}
}
}
acutPrintf(_T("\npyfunc failed: "));
}
it works fine so far.
I’m just trying to wrap my head around what’s going on here, is this correct? What happens if I launch a modeless dialog where the lock is free and the user might call back into C++? Am I setting myself up for disaster?