1

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.

Community
  • 1
  • 1
c202933
  • 31
  • 1
  • 3
  • Have you verified that you're building Eigen with debugging information? For g++, this means adding the flags `-g -ggdb`. For VS, see http://stackoverflow.com/a/4662345/2197564 – StaringFrog Nov 28 '14 at 02:19

2 Answers2

0

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

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • If I use GNU `gcc` with `Code::Blocks` and `eigen`, how I can debug to see contents of arrays? – c202933 Nov 28 '14 at 01:28
  • @c202933 you need to also use `gdb` as the debugger, and apply that python patch to `gdb`. How to do the latter I don't really know, but should be explained on that page you linked. But checkout the same page, it seems that there is also a patch for VS, https://android.googlesource.com/platform/external/eigen/+/b015e75e8c7ba1ab4ddb91e9372a57e76f3fd159/debug – vsoftco Nov 28 '14 at 01:30
0

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 ()
ThomasHH
  • 21
  • 3