Skip to content

Instantly share code, notes, and snippets.

@sbarthelemy
Created March 6, 2012 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbarthelemy/1985700 to your computer and use it in GitHub Desktop.
Save sbarthelemy/1985700 to your computer and use it in GitHub Desktop.
minimath
minimalistic almath for swig wrappers debugging
Here is a typical output:
$ python test.py
localVector: own:True this: _4063550100000000_p_std__vectorT_AL__Math__Position2D_std__allocatorT_AL__Math__Position2D_t_t
localElement: x:1.0 y:1.0 own:False this: _6063550100000000_p_AL__Math__Position2D
returnedElement: x:3.73792441723e-38 y:0.0 own:False this: _6063550100000000_p_AL__Math__Position2D
One can notice that the values in returnedElement are corrupted. The
pointers are the sames than in localElement.
/*
* Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the COPYING file.
*/
/*
* Workaround a swig problem regarding std::vector __getitem__
* Without this macro, constructs like x = myVectorPosition2D[i] return
* elements by reference and not by value, which causes problems
* when myVectorPosition2D gets garbage-collected: the C++ vector is freed
* and x holds a dandling pointer.
* With this macro, myVectorPosition2D[i] return a copy of the element.
*
* See http://thread.gmane.org/gmane.comp.programming.swig/18450
*/
%define RETURN_COPY_FROM_VECTOR(TYPE)
%typemap(out) TYPE & front {
$result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor,
SWIG_POINTER_OWN | %newpointer_flags);
}
%typemap(out) TYPE & back {
$result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor,
SWIG_POINTER_OWN | %newpointer_flags);
}
%typemap(out) TYPE & __getitem__ {
$result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor,
SWIG_POINTER_OWN | %newpointer_flags);
}
%enddef
%module almath
%feature("autodoc", "1");
%{
#include <sstream>
#include "alposition2d.h"
// forward-declare function that swig will create (thanks to the %extend
// below) and that we use to print some std::vector
static char * AL_Math_Position2D___repr__(AL::Math::Position2D *);
%}
%include "std_vector.i"
%include "std_string.i"
/* Uncomment below to fix the problem */
/*
*RETURN_COPY_FROM_VECTOR(AL::Math::Position2D)
*/
namespace std {
%template(vectorPosition2D) vector<AL::Math::Position2D>;
%extend vector<AL::Math::Position2D> {
std::string __repr__() {
std::ostringstream out;
out << "vectorPosition2D([";
if ($self->size() > 0) {
std::vector<AL::Math::Position2D>::iterator it = $self->begin();
// print all but the last element
for ( ; it<$self->end()-1; ++it)
out << AL_Math_Position2D___repr__(&(*it)) << ", ";
// print the last element, without the trailing ", "
out << AL_Math_Position2D___repr__(&(*it));
}
out << "])" << std::endl;
return out.str();
}
}
}
%include "alposition2d.h"
%extend AL::Math::Position2D {
char *__repr__() {
static char tmp[1024];
sprintf(tmp, "Position2D(x=%g, y=%g)",
$self->x, $self->y);
return tmp;
}
};
/*
* Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the COPYING file.
*/
#include <alposition2d.h>
#include <cmath>
#include <stdexcept>
namespace AL {
namespace Math {
Position2D::Position2D() : x(0.0f), y(0.0f) {}
Position2D::Position2D(float pInit) : x(pInit), y(pInit) {}
Position2D::Position2D(float pX, float pY) : x(pX), y(pY) {}
Position2D::Position2D (const std::vector<float>& pFloats)
{
if (pFloats.size() == 2)
{
x = pFloats[0];
y = pFloats[1];
}
else
{
x = 0.0f;
y = 0.0f;
}
}
Position2D Position2D::operator+ (const Position2D& pPos2) const
{
Position2D res;
res.x = x + pPos2.x;
res.y = y + pPos2.y;
return res;
}
Position2D Position2D::operator- (const Position2D& pPos2) const
{
Position2D res;
res.x = x - pPos2.x;
res.y = y - pPos2.y;
return res;
}
Position2D Position2D::operator+ () const
{
Position2D res;
res.x = x;
res.y = y;
return res;
}
Position2D Position2D::operator- () const
{
Position2D res;
res.x = -x;
res.y = -y;
return res;
}
Position2D& Position2D::operator+= (const Position2D& pPos2)
{
x += pPos2.x;
y += pPos2.y;
return *this;
}
Position2D& Position2D::operator-= (const Position2D& pPos2)
{
x -= pPos2.x;
y -= pPos2.y;
return *this;
}
bool Position2D::operator!=(const Position2D& pPos2) const
{
return !(*this==pPos2);
}
Position2D Position2D::operator* (float pVal) const
{
Position2D res;
res.x = x * pVal;
res.y = y * pVal;
return res;
}
Position2D operator* (
const float pVal,
const Position2D& pPos1)
{
return pPos1*pVal;
}
Position2D Position2D::operator/ (float pVal) const
{
if (pVal == 0.0f)
{
throw std::runtime_error(
"ALPosition2D: operator/ Division by zeros.");
}
return *this * (1.0f/pVal);
}
Position2D& Position2D::operator*= (float pVal)
{
x *=pVal;
y *=pVal;
return *this;
}
Position2D& Position2D::operator/= (float pVal)
{
if (pVal == 0.0f)
{
throw std::runtime_error(
"ALPosition2D: operator/= Division by zero.");
}
*this *= (1.0f/pVal);
return *this;
}
float Position2D::distanceSquared(const Position2D& pPos2) const
{
return Math::distanceSquared(*this, pPos2);
}
float Position2D::distance(const Position2D& pPos2) const
{
return Math::distance(*this, pPos2);
}
bool Position2D::operator==(const Position2D& pPos2) const
{
if ((x == pPos2.x) &&
(y == pPos2.y))
{
return true;
}
else
{
return false;
}
}
float distanceSquared(
const Position2D& pPos1,
const Position2D& pPos2)
{
return (pPos1.x-pPos2.x)*(pPos1.x-pPos2.x)+(pPos1.y-pPos2.y)*(pPos1.y-pPos2.y);
}
float distance(
const Position2D& pPos1,
const Position2D& pPos2)
{
return sqrtf(distanceSquared(pPos1, pPos2));
}
} // end namespace math
} // end namespace al
/*
* Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the COPYING file.
*/
#pragma once
#ifndef _LIBALMATH_ALMATH_TYPES_ALPOSITION2D_H_
#define _LIBALMATH_ALMATH_TYPES_ALPOSITION2D_H_
#include <vector>
namespace AL {
namespace Math {
/// <summary>
/// Create and play with a Position2D.
///
/// A Position2D is just defined by x and y.
/// </summary>
/// \ingroup Types
struct Position2D
{
/// <summary> </summary>
float x;
/// <summary> </summary>
float y;
/// <summary>
/// Create a Position2D initialized with 0.0f.
/**
*
* \f$ \left[\begin{array}{c}
* x \\
* y
* \end{array}\right] =
* \left[\begin{array}{c}
* 0.0 \\
* 0.0
* \end{array}\right]\f$
*/
/// </summary>
Position2D();
/// <summary>
/// Create a Position2D initialize with the same float.
/**
*
* \f$ \left[\begin{array}{c}
* x \\
* y
* \end{array}\right] =
* \left[\begin{array}{c}
* pInit \\
* pInit
* \end{array}\right]\f$
*/
/// </summary>
/// <param name="pInit"> the float value for each member </param>
/// </summary>
explicit Position2D(float pInit);
/// <summary>
/// Create a Position2D initialized with explicit value.
/**
*
* \f$ \left[\begin{array}{c}
* x \\
* y
* \end{array}\right] =
* \left[\begin{array}{c}
* pX \\
* pY
* \end{array}\right]\f$
*/
/// </summary>
/// <param name="pX"> the float value for x </param>
/// <param name="pY"> the float value for y </param>
Position2D(float pX, float pY);
/// <summary>
/// Create a Position2D with an std::vector.
/**
*
* \f$ \left[\begin{array}{c}
* x \\
* y
* \end{array}\right] =
* \left[\begin{array}{c}
* pFloats[0] \\
* pFloats[1]
* \end{array}\right]\f$
*/
/// </summary>
/// <param name="pFloats">
/// An std::vector<float> of size 2 for respectively:
/// x and y
/// </param>
Position2D(const std::vector<float>& pFloats);
/// <summary>
/// Overloading of operator + for Position2D.
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
Position2D operator+ (const Position2D& pPos2) const;
/// <summary>
/// Overloading of operator - for Position2D.
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
Position2D operator- (const Position2D& pPos2) const;
/// <summary>
/// Overloading of operator + for Position2D.
/// </summary>
Position2D operator+ () const;
/// <summary>
/// Overloading of operator - for Position2D.
/// </summary>
Position2D operator- () const;
/// <summary>
/// Overloading of operator += for Position2D.
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
Position2D& operator+= (const Position2D& pPos2);
/// <summary>
/// Overloading of operator -= for Position2D.
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
Position2D& operator-= (const Position2D& pPos2);
/// <summary>
/// Overloading of operator == for Position2D.
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
/// <returns>
/// true if each float of the two Position2D are equal
/// </returns>
bool operator==(const Position2D& pPos2) const;
/// <summary>
/// Overloading of operator != for Position2D.
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
/// <returns>
/// true if one of each float of the two Position2D are not equal
/// </returns>
bool operator!=(const Position2D& pPos2) const;
/// <summary>
/// Overloading of operator * for Position2D.
/// </summary>
/// <param name="pVal"> the float factor </param>
Position2D operator* (float pVal) const;
/// <summary>
/// Overloading of operator / for Position2D.
/// </summary>
/// <param name="pVal"> the float factor </param>
Position2D operator/ (float pVal) const;
/// <summary>
/// Overloading of operator *= for Position2D.
/// </summary>
/// <param name="pVal"> the float factor </param>
Position2D& operator*= (float pVal);
/// <summary>
/// Overloading of operator /= for Position2D.
/// </summary>
/// <param name="pVal"> the float factor </param>
Position2D& operator/= (float pVal);
/// <summary>
/// Compute the squared distance between the actual
/// Position2D and the one give in argument.
///
/// \f$(pPos1.x-pPos2.x)^2+(pPos1.y-pPos2.y)^2\f$
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
/// <returns>
/// the float squared distance between the two Position2D
/// </returns>
float distanceSquared(const Position2D& pPos2) const;
/// <summary>
/// Compute the distance between the actual
/// Position2D and the one give in argument.
///
/// \f$\sqrt{(pPos1.x-pPos2.x)^2+(pPos1.y-pPos2.y)^2}\f$
/// </summary>
/// <param name="pPos2"> the second Position2D </param>
/// <returns>
/// the float distance between the two Position2D
/// </returns>
float distance(const Position2D& pPos2) const;
};
// TODO : Need this ?
Position2D operator* (
const float pM,
const Position2D& pPos1);
/// <summary>
/// Compute the squared distance between two Position2D.
///
/// \f$(pPos1.x-pPos2.x)^2+(pPos1.y-pPos2.y)^2\f$
/// </summary>
/// <param name="pPos1"> the first Position2D </param>
/// <param name="pPos2"> the second Position2D </param>
/// <returns>
/// the float squared distance between the two Position2D
/// </returns>
/// \ingroup Types
float distanceSquared(
const Position2D& pPos1,
const Position2D& pPos2);
/// <summary>
/// Compute the distance between two Position2D \f$(pPos1,pPos2)\f$:
///
/// \f$\sqrt{(pPos1.x-pPos2.x)^2+(pPos1.y-pPos2.y)^2}\f$
/// </summary>
/// <param name="pPos1"> the first Position2D </param>
/// <param name="pPos2"> the second Position2D </param>
/// <returns>
/// the float distance between the two Position2D
/// </returns>
/// \ingroup Types
float distance(
const Position2D& pPos1,
const Position2D& pPos2);
} // end namespace math
} // end namespace al
#endif // _LIBALMATH_ALMATH_TYPES_ALPOSITION2D_H_
.PHONY:test
test:_almath.so
python test.py
alposition2d.cpp.o:alposition2d.cpp
g++ -Dalmath_EXPORTS -g -fPIC -I. -c -o $@ $<
libalmath.so:alposition2d.cpp.o alposition2d.h
g++ -fPIC -g -shared -Wl,-soname,$@ -o $@ $<
almathPYTHON_wrap.cxx:almath.i
swig -python -c++ -I. -o $@ $<
almathPYTHON_wrap.cxx.o:almathPYTHON_wrap.cxx
g++ -D_almath_EXPORTS -g -fPIC -I. -I/home/sbarthelemy/.local/share/qi/toolchains/linux64/python/include/python2.7 -c -o $@ $<
_almath.so:almathPYTHON_wrap.cxx.o libalmath.so
g++ -fPIC -g -shared -Wl,-soname,$@ -o $@ $^ -L. /home/sbarthelemy/.local/share/qi/toolchains/linux64/python/lib/libpython2.7.so -lalmath -Wl,-rpath,/home/sbarthelemy/.local/share/qi/toolchains/linux64/python/lib:.
#!/usr/bin/env python
import almath
def strswig(pos):
"""Convert a swig object into a string"""
return "own:{} this: {}".format(pos.thisown, pos.this)
def strpos(pos):
"""Convert a Position2D into a string"""
return "x:{} y:{} {}".format(pos.x, pos.y, strswig(pos))
def printpos(pos):
print(strpos(pos))
def printlist(ref):
for i in range(len(ref)):
print("[{}] {}".format(i, strpos(ref[i])))
def breakmemory():
localVector = almath.vectorPosition2D([almath.Position2D(1, 1)])
print("\nlocalVector: {}".format(strswig(localVector)))
localElement = localVector[0]
print("\nlocalElement: {}".format(strpos(localElement)))
return localElement
if __name__ == "__main__":
returnedElement = breakmemory()
print("\nreturnedElement: {}".format(strpos(returnedElement)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment