Accessing extern variable defined in a different plugin

Hi all,

I’m creating a few different plugins that share some base functionality, and I’m having trouble figuring out how I can share a single object between these separate plugins.

I have a ‘base’ plugin which contains a set of modules and defines something like

NetworkManager* manager = new NetworkManager;

And throughout the modules contained in this plugin I access this manager object just fine declaring it everywhere it’s needed with

extern NetworkManager* manager;

Now I’d like to access this object from a different plugin, compiled separately to the ‘base’ plugin. I guess since plugins in VCV are loaded at runtime, this new plugin has no knowledge of the symbol’s definition in the ‘base’ code.

Maybe someone who knows more about c++ than me can point me in the right direction? Or maybe there is a better way to approach this?

Creating one instance of the object per plugin isn’t an option, and I don’t really want to build my own version of VCV just to hold one global variable.

I was thinking there might be some way to grab the location of the symbol directly from the library file itself like how the init() function is grabbed here.

Thanks to anyone who might be able to help!

If it’s one plugin with multiple module (like most of us make), then you just need a simple global variable. If they are separate plugins (separate dlls) then it’s much more difficult.

Could you use module expanders? If a module of plugin B is next to a module of plugin A (containing the NetworkManager singleton), it could access it.

If you don’t want to require expanders, the least hacky method would be to get the Plugin pointer of plugin A from rack::plugin::plugins and if it exists, access plugin->handle and use GetProcAddress(handle, "networkManager"); or dlsym(handle, "networkManager");. Remember to extern "C" the networkManager variable in plugin A.

2 Likes

Awesome. That worked well.

I ended up using the list of plugin pointers. It doesn’t really fit to use expanders in my scenario.

Now I am doing something like:

plugin A:

extern "C" {
    NetworkManager* baseManager = new NetworkManager;
}

plugin B:

static NetworkManager *manager = NULL;

for (auto plugin : rack::plugin::plugins)
    if (plugin->slug == BASE_SLUG) {
        void *managerSym = dlsym(plugin->handle, "baseManager");
        auto managerPtr = static_cast<NetworkManager**>(managerSym);
        manager = *managerPtr;
    }

And I get pointers to the same object everywhere. Seems to be perfect for now.

Thanks a lot for your help!