From 14c65ed6db734f27228be459217462a889e9f833 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 19 Sep 2016 14:01:29 +0200 Subject: [PATCH] CdbExt: Add python scripting Introducing the script extension command that allows to run basic python code. Change-Id: I356ca5408474be0206b1c77cf2a0ecf6640ec651 Reviewed-by: Christian Stenger --- src/libs/qtcreatorcdbext/extensioncontext.cpp | 11 ++++ src/libs/qtcreatorcdbext/qtcreatorcdbext.def | 1 + src/libs/qtcreatorcdbext/qtcreatorcdbext.pro | 12 ++++ .../qtcreatorcdbext/qtcreatorcdbextension.cpp | 57 +++++++++++++++++-- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/libs/qtcreatorcdbext/extensioncontext.cpp b/src/libs/qtcreatorcdbext/extensioncontext.cpp index 1fca6c079ca..824822039ed 100644 --- a/src/libs/qtcreatorcdbext/extensioncontext.cpp +++ b/src/libs/qtcreatorcdbext/extensioncontext.cpp @@ -33,6 +33,10 @@ #include +#ifdef WITH_PYTHON +#include +#endif + // wdbgexts.h declares 'extern WINDBG_EXTENSION_APIS ExtensionApis;' // and it's inline functions rely on its existence. WINDBG_EXTENSION_APIS ExtensionApis = {sizeof(WINDBG_EXTENSION_APIS), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -155,6 +159,10 @@ HRESULT ExtensionContext::initialize(PULONG Version, PULONG Flags) *Version = DEBUG_EXTENSION_VERSION(1, 0); *Flags = 0; +#ifdef WITH_PYTHON + Py_Initialize(); +#endif + IInterfacePointer client; if (!client.create()) return client.hr(); @@ -503,6 +511,9 @@ HRESULT CALLBACK DebugExtensionInitialize(PULONG Version, PULONG Flags) void CALLBACK DebugExtensionUninitialize(void) { +#ifdef WITH_PYTHON + Py_Finalize(); +#endif } void CALLBACK DebugExtensionNotify(ULONG Notify, ULONG64) diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def index c9e9fe28d80..1535d55c0cf 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def @@ -26,3 +26,4 @@ addwatch widgetat breakpoints KnownStructOutput +script diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro index 33b957dd322..decc196bb3e 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro @@ -96,6 +96,18 @@ HEADERS += extensioncontext.h \ knowntype.h \ symbolgroupnode.h +isEmpty(PYTHON_INSTALL_DIR):PYTHON_INSTALL_DIR=$$(PYTHON_INSTALL_DIR) +exists($$PYTHON_INSTALL_DIR) { + DEFINES += WITH_PYTHON=1 + + INCLUDEPATH += $$PYTHON_INSTALL_DIR/include + DEPENDPATH += $$PYTHON_INSTALL_DIR/include + + #TODO: parse version number for a generic approach + CONFIG(release, debug|release): LIBS += -L$$PYTHON_INSTALL_DIR/libs -lpython35 + else:CONFIG(debug, debug|release): LIBS += -L$$PYTHON_INSTALL_DIR/libs -lpython35_d +} + target.path = $$QTC_PREFIX/lib/$${DIRNAME} # TODO this should go to INSTALL_LIBRARY_PATH/$${DIRNAME} INSTALLS += target diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp index f3391f7d789..2b31df6e32b 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp @@ -23,13 +23,17 @@ ** ****************************************************************************/ -#include "extensioncontext.h" -#include "outputcallback.h" #include "eventcallback.h" +#include "extensioncontext.h" +#include "gdbmihelpers.h" +#include "outputcallback.h" +#include "stringutils.h" #include "symbolgroup.h" #include "symbolgroupvalue.h" -#include "stringutils.h" -#include "gdbmihelpers.h" + +#ifdef WITH_PYTHON +#include +#endif #include #include @@ -106,7 +110,8 @@ enum Command { CmdWidgetAt, CmdBreakPoints, CmdTest, - CmdSetParameter + CmdSetParameter, + CmdScript }; static const CommandDescription commandDescriptions[] = { @@ -172,7 +177,8 @@ static const CommandDescription commandDescriptions[] = { {"breakpoints","List breakpoints with modules","[-h] [-v]"}, {"test","Testing command","-T type | -w watch-expression"}, {"setparameter","Set parameter", - "maxStringLength=value maxArraySize=value maxStackDepth=value stateNotification=1,0"} + "maxStringLength=value maxArraySize=value maxStackDepth=value stateNotification=1,0"}, +{"script", "Run Python command", "[-t token]"} }; typedef std::vector StringVector; @@ -564,6 +570,45 @@ static std::string commandLocals(ExtensionCommandContext &commandExtCtx,PCSTR ar return symGroup->dump(iname, dumpContext, parameters.dumpParameters, errorMessage); } +extern "C" HRESULT CALLBACK script(CIDebugClient *client, PCSTR argsIn) +{ + ExtensionCommandContext exc(client); + int token; +#ifdef WITH_PYTHON + std::stringstream command; + for (std::string arg : commandTokens(argsIn, &token)) + command << arg << ' '; + + if (PyRun_SimpleString(command.str().c_str()) == 0) { + ExtensionContext::instance().reportLong('R', token, "script", ""); + } else { + ExtensionContext::instance().report('N', token, 0, "script", + "Error while executing Python code."); + } + + _Py_IDENTIFIER(stdout); + _Py_IDENTIFIER(flush); + + PyObject *fout = _PySys_GetObjectId(&PyId_stdout); + PyObject *tmp; + + if (fout != NULL && fout != Py_None) { + tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); + if (tmp == NULL) + PyErr_WriteUnraisable(fout); + else + Py_DECREF(tmp); + } +#else + commandTokens(argsIn, &token); + ExtensionContext::instance().report('N', token, 0, "script", + "Python is not supported in this CDB extension.\n" + "You need to define PYTHON_INSTALL_DIR in your creator build environment " + "pointing to a Python 3.5 installation."); +#endif + return S_OK; +} + extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args) { ExtensionCommandContext exc(client);