supercollider icon indicating copy to clipboard operation
supercollider copied to clipboard

Bela: convert BelaScope to a C API

Open mossheim opened this issue 4 years ago • 1 comments

Motivation

For better ABI compatibility, best practice is to have a pure C API in public headers. SC_BelaScope.h currently doesn't do this. @giuliomoro implemented a sample C API here for Bela's Scope: https://github.com/BelaPlatform/Bela/commit/50f251ac2ec623c749dd381c49b709e0614ebbd8, which would be necessary for this purpose.

Note that I've added the "API change" but this doesn't break API because this will be the first release to contain this file.

For previous discussion, see this comment and the replies farther down.


also, i wanted to point something out about the changes to include/plugin_interface, specifically the new file SC_BelaScope.h and the BelaContext* mBelaContext and BelaScope* mBelaScope members added to World. I think we should be trying as much as possible to keep the plugin interface purely C. (see https://github.com/supercollider/supercollider/issues/4438 -- @Spacechild1 or @scztt you have both expressed interest in this topic before so I'd appreciate if one of you can comment to clarify).

that would mean the C++ class BelaScope should be replaced with a C-struct and its interface replaced with free functions for manipulating it. AFAICT BelaContext is already designed for this so nothing needs to change there (https://github.com/BelaPlatform/Bela/blob/master/include/Bela.h#L161).

Originally posted by @brianlheim in https://github.com/supercollider/supercollider/pull/5295#issuecomment-772109585

mossheim avatar Apr 02 '21 18:04 mossheim

Actually, BelaScope could be easily reduced to a pure C struct:

struct BelaScope {
    float* buffer;
    uint32_t maxChannels;
    uint32_t bufferSamples;
    bool touched; // better use int
};

In SC_Bela.cpp we can have a subclass of BelaScope, e.g. BelaScopeImp, with the (private) Scope member and logBuffer() member function, as these are not supposed to be used by plugins. Then we can initialize the BelaScope *mBelaScope member in World with a BelaScopeImp instance. We only need to be make sure to downcast it back to BelaScopeImp * before calling delete.


In general, one must never expose a C++ class with different access specifiers (public and private) to a plugin API, as the order of data members in this case is unspecified. Quote from the C++ standard:

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (11).

Spacechild1 avatar Dec 01 '23 10:12 Spacechild1