Easy enough for C style names, but what if someone wants to query C++ symbols? C++ names are mangled, is there a way around it?That's why you usually export C symbols from a plugin. I don't think anybody really tries to dynamically import C++ functions from a shared library. Even if you use C++ classes, the entry point is always a C function.
Yes this can be useful, but is this really in the scope of SFML?Well... if you have a reason to use SFML, you probably might need such a feature somewhere down the road, if you intend on working on a project for a longer period of time (and for "serious" purposes ;)).
PS: I'm really curious to know what you're developing to suddenly need such features :PI don't need it now, but I remember a while ago when I was working on an old project of mine, I wanted to be able to swap out modules that provide the same API but different implementations at runtime.
Easy enough for C style names, but what if someone wants to query C++ symbols? C++ names are mangled, is there a way around it?Declare your function extern "C". You can use C++ code in it, but the interface will be treated like a C function.
sf::Library plugin("myplugin");
initfuncsig init = plugin.getFunction("init");
if (!init)
init("init my plugin", 123);
else
std::cerr << "This is no valid plugin." << std::endl;
sf::Texture image;
image.createFromResource(plugin, som_special_way_to_identify_resource);
class DynamicLoader
{
public:
class Library
{
friend class DynamicLoader;
public:
// We dont unload our plugins manually, but here is where we would do it
// ~Library();
// return a named, exported function pointer
virtual void * getFunction(const char* inName);
// system-specific path to this loaded library
virtual const std::string& getPath() const;
protected:
void * mLibrary;
std::string mPath;
private:
Library(const char* inFile);
};
static Library * Load(const std::string& inName);
protected:
DynamicLoader();
};
#ifdef _WIN32
mLibrary = (void *) LoadLibrary(inName);
#else
mLibrary = (void *) dlopen(inName, DL_OPEN_MODE);
#endif
#ifdef _WIN32
void* funcAddr = (void *) GetProcAddress((HMODULE) mLibrary, inName);
#else
void* funcAddr = (void *) dlsym(mLibrary, inName);
#endif
extern "C"
#ifdef _WIN32
__declspec( dllexport )
#endif
Plugin* MakePlugin()
{
return new ThisSpecificPlugin();
}
DynamicLoader::Library *l = DynamicLoader::Load(plugin.c_str());
if (!l) {
throw "specified plugin '" + plugin + "' can't load!";
}
typedef Plugin* (*Plugin_Factory)();
Plugin_Factory makeit;
try {
makeit = (Plugin_Factory)l->getFunction("MakePlugin");
if (!makeit) {
throw "plugin function 'MakePlugin' not found in library!";
}
Plugin* p = makeit();
...
} catch (...) {
printf("Error during plugin initialization\n");
}
There is no reason for additional loaders, you can just use char array and loadFromMemory or create image from pixels.There's no real difference, considering no matter what, you'll get a void pointer that you have to cast. Whether you do that inside our outside your retrieval function doesn't matter.
There is also no type safety at all, so there is no (sane) way to do this:initfuncsig init = plugin.getFunction("init");But this should be possible:initfuncsig init = plugin.getFunction<initfuncsig>("init");