From c8ddfd5637f6d8e367e4fd3ef61a92d6dcd344e7 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 28 Sep 2022 04:12:11 +0200 Subject: [PATCH] Fix C++ memory layout for the TempoMap Usually C++ class instance has the same mem address as its first parent. LuaBridge uses this to for derived classes. A TemopPoint instance has the same address as its parent Tempo. However due to virtual inheritance this was not the case due to a lack of virtual d'tor. Now the following Lua code works correctly ``` tm = Temporal.TempoMap.read() tp = Temporal.timepos_t (0) print (tm:tempo_at(tp):note_type()) ``` Previously the last line failed calling Tempo::note_type() on a TempoPoint instance, due to memory offset e.g. TempoPoint: 0x600000ff90e0 Tempo: 0x600000ff90e8 --- libs/temporal/temporal/tempo.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index 8dd28c58f2..090da7ec0c 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -63,7 +63,7 @@ class TempoMap; class MapOwned { protected: MapOwned (TempoMap const & map) : _map (&map) {} - ~MapOwned () {} + virtual ~MapOwned () {} public: TempoMap const & map() const { return *_map; } @@ -174,6 +174,7 @@ class LIBTEMPORAL_API Tempo { static std::string xml_node_name; Tempo (XMLNode const &); + virtual ~Tempo () {} /** * @param npm Note Types per minute @@ -313,6 +314,8 @@ class LIBTEMPORAL_API Meter { Meter (int8_t dpb, int8_t nv) : _note_value (nv), _divisions_per_bar (dpb) {} Meter (Meter const & other) : _note_value (other._note_value), _divisions_per_bar (other._divisions_per_bar) {} + virtual ~Meter () {} + int divisions_per_bar () const { return _divisions_per_bar; } int note_value() const { return _note_value; } @@ -357,6 +360,8 @@ class /*LIBTEMPORAL_API*/ MeterPoint : public Meter, public meter_hook, public v LIBTEMPORAL_API MeterPoint (TempoMap const & map, XMLNode const &); LIBTEMPORAL_API MeterPoint (Meter const & m, Point const & p) : Point (p), Meter (m) {} + virtual ~MeterPoint () {} + LIBTEMPORAL_API Beats quarters_at (BBT_Time const & bbt) const; LIBTEMPORAL_API BBT_Time bbt_at (Beats const & beats) const; @@ -386,6 +391,8 @@ class /*LIBTEMPORAL_API*/ TempoPoint : public Tempo, public tempo_hook, public v LIBTEMPORAL_API TempoPoint (Tempo const & t, Point const & p) : Point (p), Tempo (t), _omega (0.) {} LIBTEMPORAL_API TempoPoint (TempoMap const & map, XMLNode const &); + virtual ~TempoPoint () {} + /* just change the tempo component, without moving */ LIBTEMPORAL_API TempoPoint& operator=(Tempo const & t) { *((Tempo*)this) = t; @@ -454,10 +461,11 @@ class /*LIBTEMPORAL_API*/ TempoPoint : public Tempo, public tempo_hook, public v computation code that requires both tempo and meter information every place it is used. */ -class LIBTEMPORAL_API TempoMetric { +class LIBTEMPORAL_API TempoMetric +{ public: TempoMetric (TempoPoint const & t, MeterPoint const & m) : _tempo (&t), _meter (&m) {} - ~TempoMetric () {} + virtual ~TempoMetric () {} TempoPoint const & tempo() const { return *_tempo; } MeterPoint const & meter() const { return *_meter; } @@ -538,6 +546,8 @@ class /*LIBTEMPORAL_API*/ MusicTimePoint : public bartime_hook, public virtual LIBTEMPORAL_API MusicTimePoint (TempoMap const & map, XMLNode const &); + virtual ~MusicTimePoint () {} + LIBTEMPORAL_API bool operator== (MusicTimePoint const & other) const { return TempoPoint::operator== (other) && MeterPoint::operator== (other); }