Ada interfacing C++: instance destroyed
I want to use a C++ library that implements the Factory Method design pattern.
Below you can see a minimal reproducibable example, including C++ sources and the Ada adapter.
Item.h:
// Product interface #ifndef _ITEM_H_ #define _ITEM_H_ class Item { public: virtual ~Item() = default; virtual void do_something() = 0; }; #endif
ConcreteItem.h:
#ifndef _CONCRETEITEM_H_ #define _CONCRETEITEM_H_ #include "Item.h" class ConcreteItem : public Item { public: ConcreteItem(); ~ConcreteItem(); void do_something(); }; #endif
ConcreteItem.cpp:
#include <stdlib.h> #include <iostream> #include "ConcreteItem.h" void ConcreteItem::do_something() { std::cout << "Doing stuff \n"; }; ConcreteItem::ConcreteItem() { std::cout << "Concrete Item created \n"; }; ConcreteItem::~ConcreteItem(){ std::cout << "Concrete Item destroyed \n"; };
Factory.h:
#ifndef _FACTORY_H_ #define _FACTORY_H_ #include "Item.h" class Factory { public: static Item* get_configured_item (); Factory(Factory& other) = delete; private: static Factory* factory; static Item* config_item; Factory(); ~Factory(); }; #endif
Factory.cpp:
#include "Factory.h" #include "ConcreteItem.h" Factory* Factory::factory = nullptr; Item* Factory::config_item = nullptr; Item *Factory::get_configured_item() { if (Factory::factory == nullptr) { Factory::factory = new Factory(); if (Factory::config_item == nullptr) { Factory::config_item = new ConcreteItem(); }; }; return Factory::config_item; }; Factory::Factory(){}; Factory::~Factory() { delete Factory::config_item; };
And here I have the Ada files that imports C++ symbols, generated with a call to g++ -c -fdump-ada-spec -C ./Factory.h
and doing some modifications to suite my taste:
- Factory_h.ads:
limited with Item_h; package Factory_h is type Factory is limited record null; end record with Import => True, Convention => CPP; function get_configured_item return access Item_h.Item'Class -- ./Factory.h:9 with Import => True, Convention => CPP, External_Name => "_ZN7Factory19get_configured_itemEv"; end Factory_h;
- Item_h.ads:
with Interfaces.C; package Item_h is type Item is limited interface with Import => True, Convention => CPP; -- procedure Delete_Item (this : access Item) is abstract;-- ./Item.h:8 -- -- procedure Delete_And_Free_Item (this : access Item) is abstract; -- ./Item.h:8; procedure do_something (this : access Item) is abstract; -- ./Item.h:9 end Item_h;
And finaly an Ada main to test this silly example:
with Factory_h;
with Item_h;
procedure main is
configured_item : constant access Item_h.Item'Class :=
Factory_h.get_configured_item;
begin
configured_item.do_something;
end main;
Do you know why if I comment out the Item primitives Delete_Item
and Delete_And_Free_Item
the call to do_something
is never done and the item is destroyed?
If I uncomment them everything works.
Thanks in advance!