89 lines
3.2 KiB
C++
89 lines
3.2 KiB
C++
/**
|
|
* @file CppWidgetApi.h
|
|
* @brief A C++ (not extern "C") surface living alongside
|
|
* PluginApi.h's plain C one, in the SAME plugin build. Every member
|
|
* function below keeps its real, compiler-mangled name; nothing here
|
|
* needs special handling by source/HotReload, which classifies
|
|
* symbols by their type and section, never by what their name looks
|
|
* like -- see the "Requirements on a hot-reloadable module" section of
|
|
* hot_reload.h and the "Hot reloading C++ symbols" section of
|
|
* source/HotReload/README.md for the full picture.
|
|
*
|
|
* The two methods below are reached two different ways from
|
|
* Host/Main.cpp, deliberately: see that file's comments for why.
|
|
*/
|
|
#pragma once
|
|
|
|
/**
|
|
* @brief A small C++ class whose members are defined in the plugin, not the host.
|
|
*
|
|
* Each member below keeps its real, compiler-mangled name and is reached a different way from
|
|
* Host/Main.cpp -- through the vtable, through a manually resolved mangled name, and (for the
|
|
* operator) not at all -- to show that all of them patch like any plain C function.
|
|
*/
|
|
class CppWidget
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Virtual, so that destroying a widget through a base pointer works across the
|
|
* boundary.
|
|
*/
|
|
virtual ~CppWidget() = default;
|
|
|
|
/**
|
|
* @brief Scales its input, through a virtual call.
|
|
*
|
|
* Virtual: Host/Main.cpp calls this through ordinary C++
|
|
* polymorphic dispatch (widget->virtualTick(x)) and needs no
|
|
* manual symbol lookup at all -- the call compiles down to an
|
|
* indirect call through the object's vtable slot, not a direct
|
|
* reference to this specific symbol, so it needs no link-time
|
|
* dependency on whichever plugin build actually defines it.
|
|
*
|
|
* @param input The value to scale.
|
|
* @return V1: `input * 2`. V2: `input * 3`.
|
|
*/
|
|
virtual int virtualTick(int input);
|
|
|
|
/**
|
|
* @brief Scales its input, through an ordinary out-of-line method.
|
|
*
|
|
* Calling this as widget->tick(x)
|
|
* would compile to a direct call to CppWidget::tick's own mangled
|
|
* symbol, which would need the Host to link against a plugin
|
|
* build at build time -- exactly what hot-reloading a plugin
|
|
* means avoiding. So Host/Main.cpp instead resolves it manually
|
|
* by its mangled name via hot_reload_get_symbol(), the same way
|
|
* it resolves PluginApi.h's plain C functions.
|
|
*
|
|
* @param input The value to scale.
|
|
* @return V1: `input * 2`. V2: `input * 3`.
|
|
*/
|
|
int tick(int input);
|
|
|
|
/**
|
|
* @brief An overloaded operator.
|
|
*
|
|
* Mechanically just a function with an
|
|
* unusual mangled name, reached the same manual way as tick()
|
|
* above.
|
|
*
|
|
* @param other Ignored; the operator only prints which build it is.
|
|
* @return A new, empty widget.
|
|
*/
|
|
CppWidget operator+(const CppWidget& other) const;
|
|
};
|
|
|
|
/**
|
|
* @brief Creates a widget.
|
|
*
|
|
* The one entry point Host/Main.cpp looks up by a plain, human-typed
|
|
* name -- extern "C" here for exactly the reason hot_reload.h
|
|
* recommends it: something to hand a human-readable name to, without
|
|
* needing to know or hardcode a mangled string.
|
|
*
|
|
* @return A new widget. The caller owns it and must `delete` it (safe across the plugin
|
|
* boundary here because host and plugin share one C++ runtime and allocator).
|
|
*/
|
|
extern "C" CppWidget* make_cpp_widget();
|