forked from qt-creator/qt-creator
Debugger: Let the python bridge handle reference types
Create pointer and array types in the python code. Uses the type cache which leads to less type lookup calls. Change-Id: I970bbb04da2e8051ed66b4b12dfb62076d7f214d Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -66,6 +66,15 @@ class FakeVoidType(cdbext.Type):
|
|||||||
except:
|
except:
|
||||||
return FakeVoidType('void', self.dumper)
|
return FakeVoidType('void', self.dumper)
|
||||||
|
|
||||||
|
def targetName(self):
|
||||||
|
return self.target().name()
|
||||||
|
|
||||||
|
def arrayElements(self):
|
||||||
|
try:
|
||||||
|
return int(self.typeName[self.typeName.rindex('[') + 1:self.typeName.rindex(']')])
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
def stripTypedef(self):
|
def stripTypedef(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@@ -137,11 +146,10 @@ class Dumper(DumperBase):
|
|||||||
nativeType = FakeVoidType(nativeType.name(), self)
|
nativeType = FakeVoidType(nativeType.name(), self)
|
||||||
|
|
||||||
if code == TypeCodePointer:
|
if code == TypeCodePointer:
|
||||||
return self.createPointerType(self.fromNativeType(nativeType.target()))
|
return self.createPointerType(self.lookupType(nativeType.targetName(), nativeType.moduleId()))
|
||||||
|
|
||||||
if code == TypeCodeArray:
|
if code == TypeCodeArray:
|
||||||
targetType = self.fromNativeType(nativeType.target())
|
return self.createArrayType(self.lookupType(nativeType.targetName(), nativeType.moduleId()), nativeType.arrayElements())
|
||||||
return self.createArrayType(targetType, nativeType.arrayElements())
|
|
||||||
|
|
||||||
typeId = self.nativeTypeId(nativeType)
|
typeId = self.nativeTypeId(nativeType)
|
||||||
if self.typeData.get(typeId, None) is None:
|
if self.typeData.get(typeId, None) is None:
|
||||||
@@ -389,19 +397,19 @@ class Dumper(DumperBase):
|
|||||||
else:
|
else:
|
||||||
return typeName
|
return typeName
|
||||||
|
|
||||||
def lookupType(self, typeNameIn):
|
def lookupType(self, typeNameIn, module = 0):
|
||||||
if len(typeNameIn) == 0:
|
if len(typeNameIn) == 0:
|
||||||
return None
|
return None
|
||||||
typeName = self.stripQintTypedefs(typeNameIn)
|
typeName = self.stripQintTypedefs(typeNameIn)
|
||||||
if self.typeData.get(typeName, None) is None:
|
if self.typeData.get(typeName, None) is None:
|
||||||
nativeType = self.lookupNativeType(typeName)
|
nativeType = self.lookupNativeType(typeName, module)
|
||||||
return None if nativeType is None else self.fromNativeType(nativeType)
|
return None if nativeType is None else self.fromNativeType(nativeType)
|
||||||
return self.Type(self, typeName)
|
return self.Type(self, typeName)
|
||||||
|
|
||||||
def lookupNativeType(self, name):
|
def lookupNativeType(self, name, module = 0):
|
||||||
if name.startswith('void'):
|
if name.startswith('void'):
|
||||||
return FakeVoidType(name, self)
|
return FakeVoidType(name, self)
|
||||||
return cdbext.lookupType(name)
|
return cdbext.lookupType(name, module)
|
||||||
|
|
||||||
def reportResult(self, result, args):
|
def reportResult(self, result, args):
|
||||||
self.report('result={%s}' % (result))
|
self.report('result={%s}' % (result))
|
||||||
|
@@ -169,9 +169,10 @@ static PyObject *cdbext_getNameByAddress(PyObject *, PyObject *args)
|
|||||||
static PyObject *cdbext_lookupType(PyObject *, PyObject *args) // -> Type
|
static PyObject *cdbext_lookupType(PyObject *, PyObject *args) // -> Type
|
||||||
{
|
{
|
||||||
char *type;
|
char *type;
|
||||||
if (!PyArg_ParseTuple(args, "s", &type))
|
ULONG64 module;
|
||||||
|
if (!PyArg_ParseTuple(args, "sK", &type, &module))
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
return createPythonObject(PyType::lookupType(type));
|
return createPythonObject(PyType::lookupType(type, module));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *cdbext_listOfLocals(PyObject *, PyObject *args) // -> [ Value ]
|
static PyObject *cdbext_listOfLocals(PyObject *, PyObject *args) // -> [ Value ]
|
||||||
@@ -299,7 +300,7 @@ static PyObject *cdbext_createValue(PyObject *, PyObject *args)
|
|||||||
if (offset == address) {
|
if (offset == address) {
|
||||||
DEBUG_SYMBOL_PARAMETERS params;
|
DEBUG_SYMBOL_PARAMETERS params;
|
||||||
if (SUCCEEDED(symbolGroup->GetSymbolParameters(index, 1, ¶ms))) {
|
if (SUCCEEDED(symbolGroup->GetSymbolParameters(index, 1, ¶ms))) {
|
||||||
if (params.TypeId == type->impl->getTypeId() && params.Module == type->impl->getModule())
|
if (params.TypeId == type->impl->getTypeId() && params.Module == type->impl->moduleId())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,9 +46,9 @@ PyField::PyField(std::string name, const PyType &parentType)
|
|||||||
auto extcmd = ExtensionCommandContext::instance();
|
auto extcmd = ExtensionCommandContext::instance();
|
||||||
unsigned long typeID = 0;
|
unsigned long typeID = 0;
|
||||||
if (SUCCEEDED(extcmd->symbols()->GetFieldTypeAndOffset(
|
if (SUCCEEDED(extcmd->symbols()->GetFieldTypeAndOffset(
|
||||||
d->parentType.getModule(), d->parentType.getTypeId(), d->name.c_str(),
|
d->parentType.moduleId(), d->parentType.getTypeId(), d->name.c_str(),
|
||||||
&typeID, &d->offset))) {
|
&typeID, &d->offset))) {
|
||||||
d->type = PyType(d->parentType.getModule(), typeID);
|
d->type = PyType(d->parentType.moduleId(), typeID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -81,12 +81,13 @@ static bool isArrayPointerAtPosition(const std::string &typeName, size_t positio
|
|||||||
|
|
||||||
static bool isArrayType(const std::string &typeName)
|
static bool isArrayType(const std::string &typeName)
|
||||||
{
|
{
|
||||||
if (typeName.empty() || typeName.back() != ']')
|
if (typeName.empty() || typeName.back() != ']' || (typeName.find('[') == std::string::npos))
|
||||||
return false;
|
return false;
|
||||||
// check for types like "int (*)[3]" which is a pointer to an integer array with 3 elements
|
// check for types like "int (*)[3]" which is a pointer to an integer array with 3 elements
|
||||||
const auto arrayPosition = typeName.find_first_of('[');
|
const auto arrayPosition = typeName.find_first_of('[');
|
||||||
return arrayPosition == std::string::npos
|
const bool isArrayPointer = arrayPosition != std::string::npos
|
||||||
|| arrayPosition < 3 || !isArrayPointerAtPosition(typeName, arrayPosition - 3);
|
&& arrayPosition >= 3 && isArrayPointerAtPosition(typeName, arrayPosition - 3);
|
||||||
|
return !isArrayPointer && (typeName.compare(0, 8, "__fptr()") != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG extractArraySize(const std::string &typeName, size_t openArrayPos = 0)
|
static ULONG extractArraySize(const std::string &typeName, size_t openArrayPos = 0)
|
||||||
@@ -211,31 +212,10 @@ PyType::PyType(ULONG64 module, unsigned long typeId, const std::string &name)
|
|||||||
m_name.erase(0, 6);
|
m_name.erase(0, 6);
|
||||||
if (m_name == "<function> *")
|
if (m_name == "<function> *")
|
||||||
m_name.erase(10);
|
m_name.erase(10);
|
||||||
|
|
||||||
const std::string &typeName = this->name();
|
|
||||||
if (isPointerType(typeName)) {
|
|
||||||
m_targetType.reset(new PyType(lookupType(stripPointerType(typeName), m_module)));
|
|
||||||
} else if (isArrayType(typeName)) {
|
|
||||||
const size_t openArrayPos = typeName.find_last_of('[');
|
|
||||||
if (openArrayPos != std::string::npos) {
|
|
||||||
m_targetType.reset(new PyType(lookupType(typeName.substr(0, openArrayPos), module)));
|
|
||||||
m_arraySize = extractArraySize(typeName, openArrayPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PyType::name(bool withModule) const
|
std::string PyType::name(bool withModule) const
|
||||||
{
|
{
|
||||||
if (m_targetType && m_targetType->isValid()) {
|
|
||||||
std::ostringstream str;
|
|
||||||
str << m_targetType->name(withModule);
|
|
||||||
if (m_arraySize)
|
|
||||||
str << '[' << m_arraySize << ']';
|
|
||||||
else
|
|
||||||
str << '*';
|
|
||||||
return str.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_name.empty()) {
|
if (m_name.empty()) {
|
||||||
auto symbols = ExtensionCommandContext::instance()->symbols();
|
auto symbols = ExtensionCommandContext::instance()->symbols();
|
||||||
ULONG size = 0;
|
ULONG size = 0;
|
||||||
@@ -265,12 +245,6 @@ ULONG64 PyType::bitsize() const
|
|||||||
{
|
{
|
||||||
if (!m_resolved)
|
if (!m_resolved)
|
||||||
return 0;
|
return 0;
|
||||||
if (m_targetType && m_targetType->isValid()) {
|
|
||||||
if (m_arraySize != 0)
|
|
||||||
return m_arraySize * m_targetType->bitsize();
|
|
||||||
if (m_arraySize == 0 || isPointerType(name()))
|
|
||||||
return pointerSize() * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG size = 0;
|
ULONG size = 0;
|
||||||
auto symbols = ExtensionCommandContext::instance()->symbols();
|
auto symbols = ExtensionCommandContext::instance()->symbols();
|
||||||
@@ -281,38 +255,47 @@ ULONG64 PyType::bitsize() const
|
|||||||
|
|
||||||
int PyType::code() const
|
int PyType::code() const
|
||||||
{
|
{
|
||||||
TypeCodes code = TypeCodeStruct;
|
if (!m_resolved)
|
||||||
if (!m_resolved) {
|
return TypeCodeUnresolvable;
|
||||||
code = TypeCodeUnresolvable;
|
|
||||||
} else if (m_targetType) {
|
|
||||||
if (m_targetType->isValid())
|
|
||||||
code = m_arraySize == 0 ? TypeCodePointer : TypeCodeArray;
|
|
||||||
else
|
|
||||||
code = TypeCodeUnresolvable;
|
|
||||||
} else {
|
|
||||||
const std::string &typeName = name();
|
const std::string &typeName = name();
|
||||||
if (typeName.empty())
|
if (typeName.empty())
|
||||||
TypeCodeUnresolvable;
|
return TypeCodeUnresolvable;
|
||||||
|
if (isPointerType(typeName))
|
||||||
|
return TypeCodePointer;
|
||||||
|
if (isArrayType(typeName))
|
||||||
|
return TypeCodeArray;
|
||||||
if (typeName.find("<function>") != std::string::npos)
|
if (typeName.find("<function>") != std::string::npos)
|
||||||
code = TypeCodeFunction;
|
return TypeCodeFunction;
|
||||||
else if (isIntegralType(typeName))
|
if (isIntegralType(typeName))
|
||||||
code = TypeCodeIntegral;
|
return TypeCodeIntegral;
|
||||||
else if (isFloatType(typeName))
|
if (isFloatType(typeName))
|
||||||
code = TypeCodeFloat;
|
return TypeCodeFloat;
|
||||||
}
|
return TypeCodeStruct;
|
||||||
return code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyType PyType::target() const
|
PyType PyType::target() const
|
||||||
{
|
{
|
||||||
return (m_targetType && m_targetType->isValid()) ? *m_targetType : PyType();
|
const std::string &typeName = name();
|
||||||
|
if (isPointerType(typeName) || isArrayType(typeName))
|
||||||
|
return lookupType(targetName(), m_module);
|
||||||
|
return PyType();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PyType::targetName() const
|
||||||
|
{
|
||||||
|
const std::string &typeName = name();
|
||||||
|
if (isPointerType(typeName))
|
||||||
|
return stripPointerType(typeName);
|
||||||
|
if (isArrayType(typeName))
|
||||||
|
return typeName.substr(0, typeName.find_last_of('['));
|
||||||
|
return typeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyFields PyType::fields() const
|
PyFields PyType::fields() const
|
||||||
{
|
{
|
||||||
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
|
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
|
||||||
PyFields fields;
|
PyFields fields;
|
||||||
if (m_targetType && m_targetType->isValid())
|
if (isArrayType(name()) || isPointerType(name()))
|
||||||
return fields;
|
return fields;
|
||||||
for (ULONG fieldIndex = 0;; ++fieldIndex) {
|
for (ULONG fieldIndex = 0;; ++fieldIndex) {
|
||||||
ULONG size = 0;
|
ULONG size = 0;
|
||||||
@@ -330,8 +313,6 @@ PyFields PyType::fields() const
|
|||||||
|
|
||||||
std::string PyType::module() const
|
std::string PyType::module() const
|
||||||
{
|
{
|
||||||
if (m_targetType && m_targetType->isValid())
|
|
||||||
return m_targetType->module();
|
|
||||||
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
|
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
|
||||||
ULONG size;
|
ULONG size;
|
||||||
symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, DEBUG_ANY_ID, m_module, NULL, 0, &size);
|
symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, DEBUG_ANY_ID, m_module, NULL, 0, &size);
|
||||||
@@ -343,9 +324,14 @@ std::string PyType::module() const
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG64 PyType::moduleId() const
|
||||||
|
{
|
||||||
|
return m_module;
|
||||||
|
}
|
||||||
|
|
||||||
int PyType::arrayElements() const
|
int PyType::arrayElements() const
|
||||||
{
|
{
|
||||||
return m_arraySize;
|
return extractArraySize(name());
|
||||||
}
|
}
|
||||||
|
|
||||||
PyType::TemplateArguments PyType::templateArguments()
|
PyType::TemplateArguments PyType::templateArguments()
|
||||||
@@ -379,15 +365,8 @@ PyType PyType::lookupType(const std::string &typeNameIn, ULONG64 module)
|
|||||||
trimBack(typeName);
|
trimBack(typeName);
|
||||||
trimFront(typeName);
|
trimFront(typeName);
|
||||||
|
|
||||||
if (isPointerType(typeName))
|
if (isPointerType(typeName) || isArrayType(typeName))
|
||||||
return createPointerType(lookupType(stripPointerType(typeName), module));
|
return PyType(0, 0, typeName);
|
||||||
if (isArrayType(typeName)) {
|
|
||||||
size_t openArrayPos = typeName.find_last_of('[');
|
|
||||||
if (openArrayPos == std::string::npos)
|
|
||||||
return createUnresolvedType(typeName);
|
|
||||||
return createArrayType(lookupType(typeName.substr(0, openArrayPos), module),
|
|
||||||
extractArraySize(typeName, openArrayPos));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeName.find("enum ") == 0)
|
if (typeName.find("enum ") == 0)
|
||||||
typeName.erase(0, 5);
|
typeName.erase(0, 5);
|
||||||
@@ -398,10 +377,10 @@ PyType PyType::lookupType(const std::string &typeNameIn, ULONG64 module)
|
|||||||
|
|
||||||
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
|
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
|
||||||
ULONG typeId;
|
ULONG typeId;
|
||||||
HRESULT result;
|
HRESULT result = S_FALSE;
|
||||||
if (module != 0)
|
if (module != 0 && !isIntegralType(typeName) && !isFloatType(typeName))
|
||||||
result = symbols->GetTypeId(module, typeName.c_str(), &typeId);
|
result = symbols->GetTypeId(module, typeName.c_str(), &typeId);
|
||||||
else
|
if (FAILED(result) || result == S_FALSE)
|
||||||
result = symbols->GetSymbolTypeId(typeName.c_str(), &typeId, &module);
|
result = symbols->GetSymbolTypeId(typeName.c_str(), &typeId, &module);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
return createUnresolvedType(typeName);
|
return createUnresolvedType(typeName);
|
||||||
@@ -416,28 +395,6 @@ PyType PyType::createUnresolvedType(const std::string &typeName)
|
|||||||
return unresolvedType;
|
return unresolvedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyType PyType::createPointerType(const PyType &targetType)
|
|
||||||
{
|
|
||||||
PyType pointerType;
|
|
||||||
pointerType.m_targetType.reset(new PyType(targetType));
|
|
||||||
pointerType.m_resolved = true;
|
|
||||||
return pointerType;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyType PyType::createArrayType(const PyType &elementType, unsigned long size)
|
|
||||||
{
|
|
||||||
PyType arrayType;
|
|
||||||
arrayType.m_targetType.reset(new PyType(elementType));
|
|
||||||
arrayType.m_resolved = true;
|
|
||||||
arrayType.m_arraySize = size;
|
|
||||||
return arrayType;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG64 PyType::getModule() const
|
|
||||||
{
|
|
||||||
return m_module;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long PyType::getTypeId() const
|
unsigned long PyType::getTypeId() const
|
||||||
{
|
{
|
||||||
return m_typeId;
|
return m_typeId;
|
||||||
@@ -459,9 +416,11 @@ PY_FUNC(bitsize, PY_OBJ_NAME, "k")
|
|||||||
PY_FUNC(code, PY_OBJ_NAME, "k")
|
PY_FUNC(code, PY_OBJ_NAME, "k")
|
||||||
PY_FUNC_RET_SELF(unqualified, PY_OBJ_NAME)
|
PY_FUNC_RET_SELF(unqualified, PY_OBJ_NAME)
|
||||||
PY_FUNC_RET_OBJECT(target, PY_OBJ_NAME)
|
PY_FUNC_RET_OBJECT(target, PY_OBJ_NAME)
|
||||||
|
PY_FUNC_RET_STD_STRING(targetName, PY_OBJ_NAME)
|
||||||
PY_FUNC_RET_SELF(stripTypedef, PY_OBJ_NAME)
|
PY_FUNC_RET_SELF(stripTypedef, PY_OBJ_NAME)
|
||||||
PY_FUNC_RET_OBJECT_LIST(fields, PY_OBJ_NAME)
|
PY_FUNC_RET_OBJECT_LIST(fields, PY_OBJ_NAME)
|
||||||
PY_FUNC_RET_STD_STRING(module, PY_OBJ_NAME)
|
PY_FUNC_RET_STD_STRING(module, PY_OBJ_NAME)
|
||||||
|
PY_FUNC(moduleId, PY_OBJ_NAME, "K")
|
||||||
PY_FUNC(arrayElements, PY_OBJ_NAME, "k")
|
PY_FUNC(arrayElements, PY_OBJ_NAME, "k")
|
||||||
PY_FUNC_DECL(templateArguments, PY_OBJ_NAME)
|
PY_FUNC_DECL(templateArguments, PY_OBJ_NAME)
|
||||||
{
|
{
|
||||||
@@ -484,12 +443,16 @@ static PyMethodDef typeMethods[] = {
|
|||||||
"Type without const/volatile"},
|
"Type without const/volatile"},
|
||||||
{"target", PyCFunction(target), METH_NOARGS,
|
{"target", PyCFunction(target), METH_NOARGS,
|
||||||
"Type dereferenced if it is a pointer type, element if array etc"},
|
"Type dereferenced if it is a pointer type, element if array etc"},
|
||||||
|
{"targetName", PyCFunction(targetName), METH_NOARGS,
|
||||||
|
"Typename dereferenced if it is a pointer type, element if array etc"},
|
||||||
{"stripTypedef", PyCFunction(stripTypedef), METH_NOARGS,
|
{"stripTypedef", PyCFunction(stripTypedef), METH_NOARGS,
|
||||||
"Type with typedefs removed"},
|
"Type with typedefs removed"},
|
||||||
{"fields", PyCFunction(fields), METH_NOARGS,
|
{"fields", PyCFunction(fields), METH_NOARGS,
|
||||||
"List of fields (member and base classes) of this type"},
|
"List of fields (member and base classes) of this type"},
|
||||||
{"module", PyCFunction(module), METH_NOARGS,
|
{"module", PyCFunction(module), METH_NOARGS,
|
||||||
"Returns name for the module containing this type"},
|
"Returns name for the module containing this type"},
|
||||||
|
{"moduleId", PyCFunction(moduleId), METH_NOARGS,
|
||||||
|
"Returns id for the module containing this type"},
|
||||||
{"arrayElements", PyCFunction(arrayElements), METH_NOARGS,
|
{"arrayElements", PyCFunction(arrayElements), METH_NOARGS,
|
||||||
"Returns the number of elements in an array or 0 for non array types"},
|
"Returns the number of elements in an array or 0 for non array types"},
|
||||||
{"templateArguments", PyCFunction(templateArguments), METH_NOARGS,
|
{"templateArguments", PyCFunction(templateArguments), METH_NOARGS,
|
||||||
|
@@ -43,8 +43,10 @@ public:
|
|||||||
ULONG64 bitsize() const;
|
ULONG64 bitsize() const;
|
||||||
int code() const;
|
int code() const;
|
||||||
PyType target() const;
|
PyType target() const;
|
||||||
|
std::string targetName() const;
|
||||||
PyFields fields() const;
|
PyFields fields() const;
|
||||||
std::string module() const;
|
std::string module() const;
|
||||||
|
ULONG64 moduleId() const;
|
||||||
int arrayElements() const;
|
int arrayElements() const;
|
||||||
|
|
||||||
struct TemplateArgument
|
struct TemplateArgument
|
||||||
@@ -61,7 +63,6 @@ public:
|
|||||||
|
|
||||||
TemplateArguments templateArguments();
|
TemplateArguments templateArguments();
|
||||||
|
|
||||||
ULONG64 getModule() const;
|
|
||||||
unsigned long getTypeId() const;
|
unsigned long getTypeId() const;
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
@@ -69,13 +70,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static PyType createUnresolvedType(const std::string &typeName);
|
static PyType createUnresolvedType(const std::string &typeName);
|
||||||
static PyType createPointerType(const PyType &pointerType);
|
|
||||||
static PyType createArrayType(const PyType &targetType, unsigned long size);
|
|
||||||
|
|
||||||
unsigned long m_typeId = 0;
|
unsigned long m_typeId = 0;
|
||||||
ULONG64 m_module = 0;
|
ULONG64 m_module = 0;
|
||||||
unsigned long m_arraySize = 0;
|
|
||||||
std::shared_ptr<PyType> m_targetType;
|
|
||||||
bool m_resolved = false;
|
bool m_resolved = false;
|
||||||
mutable std::string m_name;
|
mutable std::string m_name;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user