Pretty printing boost::unordered_map on gdb - c++

recently I've started to use the excellent boost::unordered_map on my system, but got one drawback: I couldn't figure how to inspect its contents. Printing it on gdb gives me a table_ and a buckets_, but haven't found where are the items. Anyone has a clue about this?

For the ones that wanted a printer, I've managed to create one. Here is Code:
class BoostUnorderedMapPrinter:
"prints a boost::unordered_map"
class _iterator:
def __init__ (self, fields):
type_1 = fields.val.type.template_argument(0)
type_2 = fields.val.type.template_argument(1)
self.buckets = fields.val['table_']['buckets_']
self.bucket_count = fields.val['table_']['bucket_count_']
self.current_bucket = 0
pair = "std::pair<%s const, %s>" % (type_1, type_2)
self.pair_pointer = gdb.lookup_type(pair).pointer()
self.base_pointer = gdb.lookup_type("boost::unordered_detail::value_base< %s >" % pair).pointer()
self.node_pointer = gdb.lookup_type("boost::unordered_detail::hash_node<std::allocator< %s >, boost::unordered_detail::ungrouped>" % pair).pointer()
self.node = self.buckets[self.current_bucket]['next_']
def __iter__(self):
return self
def next(self):
while not self.node:
self.current_bucket = self.current_bucket + 1
if self.current_bucket >= self.bucket_count:
raise StopIteration
self.node = self.buckets[self.current_bucket]['next_']
iterator = self.node.cast(self.node_pointer).cast(self.base_pointer).cast(self.pair_pointer).dereference()
self.node = self.node['next_']
return ('%s' % iterator['first'], iterator['second'])
def __init__(self, val):
self.val = val
def children(self):
return self._iterator(self)
def to_string(self):
return "boost::unordered_map"

In a typical hash table implementation, the buckets contain the head of a linked list which actually contains the values corresponding to this particular hash. Thus I would bet on buckets_.
Another option: there are various python pretty printer libraries for gdb now, and I think that you could find one that works with C++0x and inspect where it looks for the values.

Related

object returning memory location instead of value

So I have this class:
#!/usr/bin/python3
class MyClass(object):
def __init__(self, length):
self._list = length
def get(self, index):
try:
return self._list[index]
except IndexError:
return None
which takes in a list and returns a value, a list index I think. I am trying to get that value:
def my_function(a_list):
a_list = MyClass
for x in (10**p for p in range(1, 9)):
if a_list:
print(a_list)
def main():
length = my_function(MyClass([i for i in range(0, 543)]))
but I keep getting only the memory location of the list, I think this is supposed to return an int.
I am hoping this is a workable bit of code, but I am struggling, with the concept of passing an "object" to a class, it doesn't make any sense to me.
Here is a test I am supposed to use:
def test_large_list():
s_list = My_Class([i for i in xrange(0, 100000)])
assert len(s_list._list) == list_length(s_list)
Ok, Here is my full function that works, it is done, how od I do this so that the first line takes an argument
#!/usr/bin/python3
#def list_length(single_method_list): This is what I am supposed to work with
from single_method_list import SingleMethodList
def my_function(): # This is how I have done it and it works.
a_list = MyClass([i for i in range(0, 234589)])
for x in (10**p for p in range(1, 8)):
if a_list.get(x):
print("More than", x)
first = x
else:
print("Less than", x)
last = x
break
answer = False
while not answer:
result = (first + last)/2
result = int(round(result))
print(result)
if s_list.get(result):
first = result
print('first', result)
else:
last = result
print('last', result)
if s_list.get(result) and not s_list.get(result + 1):
answer = True
print(result + 1)
my_function()
I don't know what more I can give to explain where I am stuck, it is the OOP part of this that I don't know I need the same results here, just passing it to the function instead of creating it inside the function which I did in order to do the algorithm.
Well your class does something else.MyClass is designed to take a List at initialization, so the naming length is not a good idea.
The get() method of this class takes in a number and returns the element located at that particular index in the initialized self._list.
Your logic should be like:
def my_function(a_list):
a_list = MyClass(a_list)
...
def main():
length = my_function([i for i in range(0, 543)])
Just to clarify some misunderstanding that you might have.
Class does not return anything. It is a blueprint for creating objects.
What can return value is a method (function). For instance, if you want to write a method which returns length of some list:
def my_function(some_list):
return len(some_list)
Or in your case:
def my_function(a_list):
return len(a_list._list)
Note that you should not call your variables list. It's a built-in function in python which creates lists.
And as you can see there is another built-in function len in python which returns length of list, tuple, dictionary etc.
Hope this helps, although it's still a bit unclear what you're trying to achieve.

Calling a list from another function in Python

I am trying figure out if I'm having an issue with my classes, or calling variables/lists from another function.
Below is a function I have being called from a button I press(inside a class that is my main window):
def analyzeRNA(self):
self.p = self.textbox.get("1.0", END)
protein_assignment(self.p)
self.data = primary_structure
self.databox.insert(END, self.data)
It reads from my textbox just fine. It performs my function protein_assignment on it and prints the results to the python shell as in the function does. It prints a list I make in protein_assignment that function called primary_structure. Now, how do put this information into my databox (which is also a "textbox" so to speak)
My error:
line 86, in analyzeRNA
self.data = primary_structure
NameError: global name 'primary_structure' is not defined
Protein assignment outline:
def protein_assignment(sequence):
x = 0
primary_structure = []
single_letter_assignment = []
three_letter_code = []
chemical_properties = []
while True:
blah, blah, blah adding amino acids to the list, running through sequence
"if nothing else in sequence, print lists and break"
return primary_structure #(Not sure if this is needed)
return primary_structure #(Not sure what I'm doing here either)
If more is needed, glad to help. Running off to work right now. Will respond later. Please and thank you!
primary_structure is returned by protein_assignment so to keep a reference to it in analyzeRNA you just need to do this:
def analyzeRNA(self):
self.p = self.textbox.get("1.0", END)
returned_value = protein_assignment(self.p)
self.data = returned_value
self.databox.insert(END, self.data)
or since you are just setting it to self.data anyway:
def analyzeRNA(self):
self.p = self.textbox.get("1.0", END)
self.data = protein_assignment(self.p)
self.databox.insert(END, self.data)

Best approach to create an saturating integer in python?

What would be the best approach to create a type that is a saturated integer in python ?
i.e.:
v = SaturatedInteger(0, 100)
# That should create an integer that will always be in between 0 and 100,
# and have all default operations
v += 68719
print v #Should print '100'.
I can think of inheriting int type, but where should the saturating logic be implemented then ?
If you need a new (quick and dirty) class for it, I would implement it as follows.
class SaturatedInteger:
def __init__(self, val, lo, hi):
self.real, self.lo, self.hi = val, lo, hi
def __add__(self, other):
return min(self.real + other.real, self.hi)
def __sub__(self, other):
return max(self.real - other.real, self.lo)
...
Add as many of the other operators in the docs as you feel you will need (and their 'r' variants).
By storing the value in the instance name real, you can do your arithmetic with regular integers, floats, etc. too:
a = SaturatedInteger(60, 0, 100)
print(a)
60
print(a+30)
90
print(a+40)
100
print(a+50.)
100
print(a-70.)
0
print(a+a)
100
Though, of course you only add the real part if you're adding a complex number to your SaturatedInteger, so watch out. (For a much more complete and robust version, #jonrsharpe's answer is the way to go).
In general, I would implement using a #property to protect an instance's value attribute, then emulate a numeric type, rather than inheriting from int:
class SaturatedInteger(object):
"""Emulates an integer, but with a built-in minimum and maximum."""
def __init__(self, min_, max_, value=None):
self.min = min_
self.max = max_
self.value = min_ if value is None else value
#property
def value(self):
return self._value
#value.setter
def value(self, new_val):
self._value = min(self.max, max(self.min, new_val))
#staticmethod
def _other_val(other):
"""Get the value from the other object."""
if hasattr(other, 'value'):
return other.value
return other
def __add__(self, other):
new_val = self.value + self._other_val(other)
return SaturatedInteger(self.min, self.max, new_val)
__radd__ = __add__
def __eq__(self, other):
return self.value == self._other_val(other)
if __name__ == '__main__':
v = SaturatedInteger(0, 100)
v += 68719
assert v == 100
assert 123 + v == 100
I've only implemented __add__, __radd__ and __eq__, but you can probably see how the rest could be built out as required. You might want to think about what happens when two SaturatedIntegers are used together - should the result have e.g. min(self.min, other.min) as its own min?
I wrote a sample class that has an add function:
class SatInt:
def __init__(self, low, up):
self.lower = low
self.upper = up
self.value = 0
def add(self, n):
if n+self.value > self.upper:
self.value = self.upper
else:
self.value = self.value + n
x = SatInt(0,100)
x.add(32718)
print(x.value)
100

How to debug with gdb with eigen math library

I used code::blocks (CB) or visual studio (VS) for C++ programs with eigen library. However, when it comes to debugging, I cannot see contents of arrays, matrices etc. I checked following posts:
Using GDB with Eigen C++ library
I am not a C++ expert but I could get that I need something called as printer.
https://android.googlesource.com/platform/external/eigen/+/b015e75e8c7ba1ab4ddb91e9372a57e76f3fd159/debug/gdb/printers.py has the source code. However I do not know how to use this source code to debug with gdb with eigen library in CB or VS. Any ideas how to do this?
Update:
vsoftco mentioned a webpage https://android.googlesource.com/platform/external/eigen/+/b015e75e8c7ba1ab4ddb91e9372a57e76f3fd159/debug and that has python printers for gdb for CB and VS. If anyone knows how to use them to see contents of arrays of eigen library, please comment.
The Eigen::Matrix class is not an aggregate, so you cannot just see its content with a debugger. However, you should be able to step in with a debugger, and can use cout or other methods to display the content.
The link you mentioned is a python plugin for gdb, to allow gdb to print the content of Eigen types. But as you use VS (which has its internal debugger and doesn't use gdb), there is no reason why it would work in your case.
You can try switching to MinGW and g++/gdb, or can check this link How can I use GDB from inside Visual Studio C++ (Express) to debug my GCC Makefile projects? for some advice about installing gdb under VS.
PS: it seems that a solution for VS also exists,
https://android.googlesource.com/platform/external/eigen/+/b015e75e8c7ba1ab4ddb91e9372a57e76f3fd159/debug
The python printers for gdb works for me. Notice that the printers.py script is written in Python 2.7 and your gdb is probably running python 3.5 or later... Use the 2to3 converter or simply copy this to a new file called printers3.py:
# -*- coding: utf-8 -*-
# This file is part of Eigen, a lightweight C++ template library
# for linear algebra.
#
# Copyright (C) 2009 Benjamin Schindler <bschindler#inf.ethz.ch>
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Pretty printers for Eigen::Matrix
# This is still pretty basic as the python extension to gdb is still pretty basic.
# It cannot handle complex eigen types and it doesn't support any of the other eigen types
# Such as quaternion or some other type.
# This code supports fixed size as well as dynamic size matrices
# To use it:
#
# * Create a directory and put the file as well as an empty __init__.py in
# that directory.
# * Create a ~/.gdbinit file, that contains the following:
# python
# import sys
# sys.path.insert(0, '/path/to/eigen/printer/directory')
# from printers3 import register_eigen_printers
# register_eigen_printers (None)
# end
import gdb
import re
import itertools
class EigenMatrixPrinter:
"Print Eigen Matrix or Array of some kind"
def __init__(self, variety, val):
"Extract all the necessary information"
# Save the variety (presumably "Matrix" or "Array") for later usage
self.variety = variety
# The gdb extension does not support value template arguments - need to extract them by hand
type = val.type
if type.code == gdb.TYPE_CODE_REF:
type = type.target()
self.type = type.unqualified().strip_typedefs()
tag = self.type.tag
regex = re.compile('\<.*\>')
m = regex.findall(tag)[0][1:-1]
template_params = m.split(',')
template_params = [x.replace(" ", "") for x in template_params]
if template_params[1] == '-0x00000000000000001' or template_params[1] == '-0x000000001' or template_params[1] == '-1':
self.rows = val['m_storage']['m_rows']
else:
self.rows = int(template_params[1])
if template_params[2] == '-0x00000000000000001' or template_params[2] == '-0x000000001' or template_params[2] == '-1':
self.cols = val['m_storage']['m_cols']
else:
self.cols = int(template_params[2])
self.options = 0 # default value
if len(template_params) > 3:
self.options = template_params[3];
self.rowMajor = (int(self.options) & 0x1)
self.innerType = self.type.template_argument(0)
self.val = val
# Fixed size matrices have a struct as their storage, so we need to walk through this
self.data = self.val['m_storage']['m_data']
if self.data.type.code == gdb.TYPE_CODE_STRUCT:
self.data = self.data['array']
self.data = self.data.cast(self.innerType.pointer())
class _iterator:
def __init__ (self, rows, cols, dataPtr, rowMajor):
self.rows = rows
self.cols = cols
self.dataPtr = dataPtr
self.currentRow = 0
self.currentCol = 0
self.rowMajor = rowMajor
def __iter__ (self):
return self
def __next__(self):
row = self.currentRow
col = self.currentCol
if self.rowMajor == 0:
if self.currentCol >= self.cols:
raise StopIteration
self.currentRow = self.currentRow + 1
if self.currentRow >= self.rows:
self.currentRow = 0
self.currentCol = self.currentCol + 1
else:
if self.currentRow >= self.rows:
raise StopIteration
self.currentCol = self.currentCol + 1
if self.currentCol >= self.cols:
self.currentCol = 0
self.currentRow = self.currentRow + 1
item = self.dataPtr.dereference()
self.dataPtr = self.dataPtr + 1
if (self.cols == 1): #if it's a column vector
return ('[%d]' % (row,), item)
elif (self.rows == 1): #if it's a row vector
return ('[%d]' % (col,), item)
return ('[%d,%d]' % (row, col), item)
def children(self):
return self._iterator(self.rows, self.cols, self.data, self.rowMajor)
def to_string(self):
return "Eigen::%s<%s,%d,%d,%s> (data ptr: %s)" % (self.variety, self.innerType, self.rows, self.cols, "RowMajor" if self.rowMajor else "ColMajor", self.data)
class EigenQuaternionPrinter:
"Print an Eigen Quaternion"
def __init__(self, val):
"Extract all the necessary information"
# The gdb extension does not support value template arguments - need to extract them by hand
type = val.type
if type.code == gdb.TYPE_CODE_REF:
type = type.target()
self.type = type.unqualified().strip_typedefs()
self.innerType = self.type.template_argument(0)
self.val = val
# Quaternions have a struct as their storage, so we need to walk through this
self.data = self.val['m_coeffs']['m_storage']['m_data']['array']
self.data = self.data.cast(self.innerType.pointer())
class _iterator:
def __init__ (self, dataPtr):
self.dataPtr = dataPtr
self.currentElement = 0
self.elementNames = ['x', 'y', 'z', 'w']
def __iter__ (self):
return self
def __next__(self):
element = self.currentElement
if self.currentElement >= 4: #there are 4 elements in a quanternion
raise StopIteration
self.currentElement = self.currentElement + 1
item = self.dataPtr.dereference()
self.dataPtr = self.dataPtr + 1
return ('[%s]' % (self.elementNames[element],), item)
def children(self):
return self._iterator(self.data)
def to_string(self):
return "Eigen::Quaternion<%s> (data ptr: %s)" % (self.innerType, self.data)
def build_eigen_dictionary ():
pretty_printers_dict[re.compile('^Eigen::Quaternion<.*>$')] = lambda val: EigenQuaternionPrinter(val)
pretty_printers_dict[re.compile('^Eigen::Matrix<.*>$')] = lambda val: EigenMatrixPrinter("Matrix", val)
pretty_printers_dict[re.compile('^Eigen::Array<.*>$')] = lambda val: EigenMatrixPrinter("Array", val)
def register_eigen_printers(obj):
"Register eigen pretty-printers with objfile Obj"
if obj == None:
obj = gdb
obj.pretty_printers.append(lookup_function)
def lookup_function(val):
"Look-up and return a pretty-printer that can print va."
type = val.type
if type.code == gdb.TYPE_CODE_REF:
type = type.target()
type = type.unqualified().strip_typedefs()
typename = type.tag
if typename == None:
return None
for function in pretty_printers_dict:
if function.search(typename):
return pretty_printers_dict[function](val)
return None
pretty_printers_dict = {}
build_eigen_dictionary ()

Issues with recursive calls while building a Tree datastructure

I've been trying to figure out how to recursively call a function in python for the last few days to no avail. I'm building a tree structure to store objects and have issues with not only traversing the tree using a generator, but also with making recursive calls to my find function.
Here is my code.
class Node:
def __init__(self, data, children=list()):
self.data = data
self.children = children
def __eq__(self, node):
return self.data == node.data
def __str__(self):
return self.data
def __repr__(self):
return self.data
def write_xtl(self, node, out_file, level=0):
gen2 = self.traverse(node)
for child in gen2:
out_file.write(child.data)
def traverse(self, node, path=list()):
yield self
for n in self.children:
for m in traverse(n, path):
yield m
def find(self, node):
if self == node:
return self
else:
for child in self.children:
return child.find(node)
def add(self, node, value):
entry_point = self.find(node)
if entry_point:
#print ("Found %s in %s") % (value.data.rstrip(), node.data.rstrip())
#print ("\tentry_point is %s") % (entry_point.data)
entry_point.children.append(value)
else:
print ("Could not find %s") % (value)
Here's my test file:
from xtensiltree import tree
root = tree.Node("root\n")
header = tree.Node("header\n")
orderHeader = tree.Node("orderHeader\n")
date = tree.Node("date\n")
notes = tree.Node("notes\n")
address = tree.Node("address\n")
contacts = tree.Node("contacts\n")
root.add(root, header)
root.add(header, orderHeader)
root.add(orderHeader, date)
root.add(orderHeader, notes)
root.add(orderHeader, address)
root.add(address, contacts)
outfile = open("ooutput.xtl", "w")
root.write_xtl(root, outfile)
outfile.close()
Thank you in advance.
Here is some example how find method should look like.
def find(self, node):
if self == node:
return self
elif self.children != []:
for child in self.children:
found = child.find(node)
if found:
return found
return None
Basicly, it means: if the current node is what we are looking for then return it. If not and the current node has children search them. If it's been found in one of children it will be returned, otherwise return None.
My problem was with my init() method.
def init(self, data, children=list()):
The list in my tree was declared global. This caused every element of my tree to have the same children.
In turn, any recursive functions would go on forever.
Thanks for the help Tiero.