forked from qt-creator/qt-creator
CdbExt: Add python scripting
Introducing the script extension command that allows to run basic python code. Change-Id: I356ca5408474be0206b1c77cf2a0ecf6640ec651 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -33,6 +33,10 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifdef WITH_PYTHON
|
||||||
|
#include <Python.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// wdbgexts.h declares 'extern WINDBG_EXTENSION_APIS ExtensionApis;'
|
// wdbgexts.h declares 'extern WINDBG_EXTENSION_APIS ExtensionApis;'
|
||||||
// and it's inline functions rely on its existence.
|
// 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};
|
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);
|
*Version = DEBUG_EXTENSION_VERSION(1, 0);
|
||||||
*Flags = 0;
|
*Flags = 0;
|
||||||
|
|
||||||
|
#ifdef WITH_PYTHON
|
||||||
|
Py_Initialize();
|
||||||
|
#endif
|
||||||
|
|
||||||
IInterfacePointer<CIDebugClient> client;
|
IInterfacePointer<CIDebugClient> client;
|
||||||
if (!client.create())
|
if (!client.create())
|
||||||
return client.hr();
|
return client.hr();
|
||||||
@@ -503,6 +511,9 @@ HRESULT CALLBACK DebugExtensionInitialize(PULONG Version, PULONG Flags)
|
|||||||
|
|
||||||
void CALLBACK DebugExtensionUninitialize(void)
|
void CALLBACK DebugExtensionUninitialize(void)
|
||||||
{
|
{
|
||||||
|
#ifdef WITH_PYTHON
|
||||||
|
Py_Finalize();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK DebugExtensionNotify(ULONG Notify, ULONG64)
|
void CALLBACK DebugExtensionNotify(ULONG Notify, ULONG64)
|
||||||
|
|||||||
@@ -26,3 +26,4 @@ addwatch
|
|||||||
widgetat
|
widgetat
|
||||||
breakpoints
|
breakpoints
|
||||||
KnownStructOutput
|
KnownStructOutput
|
||||||
|
script
|
||||||
|
|||||||
@@ -96,6 +96,18 @@ HEADERS += extensioncontext.h \
|
|||||||
knowntype.h \
|
knowntype.h \
|
||||||
symbolgroupnode.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}
|
target.path = $$QTC_PREFIX/lib/$${DIRNAME} # TODO this should go to INSTALL_LIBRARY_PATH/$${DIRNAME}
|
||||||
|
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
|
|||||||
@@ -23,13 +23,17 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "extensioncontext.h"
|
|
||||||
#include "outputcallback.h"
|
|
||||||
#include "eventcallback.h"
|
#include "eventcallback.h"
|
||||||
|
#include "extensioncontext.h"
|
||||||
|
#include "gdbmihelpers.h"
|
||||||
|
#include "outputcallback.h"
|
||||||
|
#include "stringutils.h"
|
||||||
#include "symbolgroup.h"
|
#include "symbolgroup.h"
|
||||||
#include "symbolgroupvalue.h"
|
#include "symbolgroupvalue.h"
|
||||||
#include "stringutils.h"
|
|
||||||
#include "gdbmihelpers.h"
|
#ifdef WITH_PYTHON
|
||||||
|
#include <Python.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -106,7 +110,8 @@ enum Command {
|
|||||||
CmdWidgetAt,
|
CmdWidgetAt,
|
||||||
CmdBreakPoints,
|
CmdBreakPoints,
|
||||||
CmdTest,
|
CmdTest,
|
||||||
CmdSetParameter
|
CmdSetParameter,
|
||||||
|
CmdScript
|
||||||
};
|
};
|
||||||
|
|
||||||
static const CommandDescription commandDescriptions[] = {
|
static const CommandDescription commandDescriptions[] = {
|
||||||
@@ -172,7 +177,8 @@ static const CommandDescription commandDescriptions[] = {
|
|||||||
{"breakpoints","List breakpoints with modules","[-h] [-v]"},
|
{"breakpoints","List breakpoints with modules","[-h] [-v]"},
|
||||||
{"test","Testing command","-T type | -w watch-expression"},
|
{"test","Testing command","-T type | -w watch-expression"},
|
||||||
{"setparameter","Set parameter",
|
{"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<std::string> StringVector;
|
typedef std::vector<std::string> StringVector;
|
||||||
@@ -564,6 +570,45 @@ static std::string commandLocals(ExtensionCommandContext &commandExtCtx,PCSTR ar
|
|||||||
return symGroup->dump(iname, dumpContext, parameters.dumpParameters, errorMessage);
|
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<StringList>(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<StringList>(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)
|
extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)
|
||||||
{
|
{
|
||||||
ExtensionCommandContext exc(client);
|
ExtensionCommandContext exc(client);
|
||||||
|
|||||||
Reference in New Issue
Block a user