My main program would load a simple dynamic library called hello.so
In main
void* handle = dlopen("./hello.so", RTLD_LAZY);
In main , pass a callback function called testing (defined somewhere in main.h) and invoke the hello() from the dynamic library
typedef void (*callback)();
typedef void (*hello_t)( callback);
/* do something */
hello_t hello = (hello_t) dlsym(handle, "hello");
hello(testing);
In dynamic library,
#include
#include "main.h"
extern "C" void hello( void (*fn)() ) {
/*do something and then invoke callback function from main */ fn();
}
Are there other ways to allow functions/data of main to be called/used from dynamic library apart from using callbacks?
No, this is the preferred way of doing it, in my opinion. Any other way that I can think of involves making the DLL aware of the objects in the program it's linked with, which is most likely bad practice.
Regarding data, just a reminder though you didn't ask, it's usually best practice to copy any data that needs to be stored, if it's passed across library/program boundaries. You can get into a complete mess if you have the library using data whose lifetime is controlled by the program, and vice versa.
Related
I have some code that is compiled as a shared library and used with a universal driver, which can be used with other shared libraries that are specific to a particular application.
My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.
For example, let's say I have 3 files, the first is driver.cpp, the universal driver:
#include "interface.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
//perform a function from the shared library
std::cout << foobar() << std::endl;
}
The second is sharedlibrary.cpp, the specific implementation for one case of many:
#include "interface.h"
char* foobar() {
return x;
}
Where x is some indicator that this function is defined in sharedlibrary.cpp, or that this function is linked from sharedlibrary.so, or the current stack frame is using the specific binary rather than just being included in driver.cpp.
The last file is interface.h, which provides the interface to the library via extern "C"
extern "C" {
char foobar();
}
I would like to reiterate, for clarity, that I am looking for some indication that this function is being linked from sharedlibrary.so. Many solutions looking for runtime filenames give the executable name using either argv[0] or readlink(), but I have no control over the actual naming of driver.cpp or its executable name. Rather, I can distribute sharedlibrary.so, and would like to be able to use its name from within itself, if possible.
If it helps, I know that a microsoft-specific solution could be to use AfxGetApp()->m_pszAppName to obtain the DLL name. However, I am looking for a linux solution that does not necessarily need to be portable.
EDIT: I do not know or control the names of driver.cpp, sharedlibrary.cpp, or sharedlibrary.h at compile time. I wish to discover the name of sharedlibrary.cpp at run time.
The updated sharedlibrary.cpp with x replaced with the solution looks like this
#include "interface.h"
#include <dlfcn.h>
void func() {
//Some function that is defined in sharedlibrary.cpp
}
char* foobar() {
Dl_info DlInfo;
if(!dladdr((void*)func, &DlInfo)) {
return "default_name";
}
return DlInfo.dli_fname;
}
Obtaining filename at runtime for a shared library c++
My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.
You can use int dladdr(void *addr, Dl_info *info. It fills a following structure for you:
typedef struct {
const char *dli_fname; /* Pathname of shared object that contains address */
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
} Dl_info;
You can pass the address of a function exported by the shared library as the argument addr. Or within such function, you could use the instruction pointer value of the current stack frame - if you know how to obtain it.
I believe you must link with the libdl library.
You can use the buildsystem to generate the dynamic library name for linking and preprocess that inside of a header with a function that return a defined macro, in cmake you can see how to do that here.
Then you use the configured-file to return the defined value in a function that's exported from within the dll.
#include "library_name_macro.h"
auto __dllexport libraryName() -> std::string { return LIBRARY_NAME_MACRO; }
I hope, I have understood your question correctly. I hope my answer helps. You know the shared library name, you link that shared library to your program, Later in run time you want to figure out whether a particular function is present in library or not and this logic should be part of shared library itself.
Let's take an example that you have shared library called librandom.so, You have linked this library to your application. You can implement the following function in a librandom.so library, You can pass function name which you want to check whether it is present or not. I have not tested this code, there may be errors. The idea I am proposing is library loads itself again to check whether the function is present when this function is called. May not be ideal method but should serve your purpose.
int isFuncPresent(char funcName[])
{
int isFuncFound = 1;
void *lib_handle;
int x;
char *error;
lib_handle = dlopen("librandom.so", RTLD_LAZY);
if (!lib_handle)
{
fprintf(stderr, "%s\n", dlerror());
isFuncFound = 0;
}
fn = dlsym(lib_handle, funcName);
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
isFuncFound = 0;
}
dlclose(lib_handle);
return isFuncFound;
}
Let I have a header, for example #include <GL/gl.h>. It contains subset of OpenGL API functions. I need something like this:
static_assert(has_glDrawArraysIndirect::value, "There is no glDrawArraysIndirect");
Or even better:
PFNGLDRAWARRAYSINSTANCEDPROC ptr_glDrawArraysIndirect = ptr_to_glDrawArraysIndirect::ptr;
Where ptr_to_glDrawArraysIndirect::ptr unrolls to pointer to glDrawArraysIndirect if it's defined or to a stub function stub_glDrawArraysIndirect otherwise.
My target operating system is very specific. Any linker based solution (like GetProcAddress or dlsym) doesn't work for me, since there is no dynamic linker. More than, my driver doesn't provide glXGetProcAdrress nor wglGetProcAddress, basically there there is no way to query pointer at run time by function name (Actually, I want to implement such a mechanism).
Any ideas?
Here is an answer that can detect it at compile time and produce a boolean value. It works by creating a template function of the same name in a namespace and then using that namespace inside of the is_defined() function. If the real glDrawArraysIndirect() exists it will take preference over the template version. If you comment out the first declaration of glDrawArraysIndirect() the static assert at the bottom will trigger.
Test on GodBolt
#include <type_traits>
enum GLenum {};
void glDrawArraysIndirect(GLenum, const void*);
namespace detail {
struct dummy;
template<typename T>
dummy& glDrawArraysIndirect(T, const void*);
}
constexpr bool is_defined()
{
using namespace detail;
using ftype = decltype(glDrawArraysIndirect(GLenum(), nullptr));
return std::is_same<ftype, void>();
}
static_assert(is_defined(), "not defined");
With a little tweak you can make your custom function the template and use a similar trick
ideone.com
#include <type_traits>
#include <iostream>
//#define USE_REAL
enum GLenum {TEST};
typedef void (*func_type)(GLenum, const void*);
#ifdef USE_REAL
void glDrawArraysIndirect(GLenum, const void*);
#endif
namespace detail {
struct dummy {};
template<typename T = dummy>
void glDrawArraysIndirect(GLenum, const void*, T = T())
{
std::cout << "In placeholder function" << std::endl;
}
}
void wrapDraw(GLenum x, const void* y)
{
using namespace detail;
glDrawArraysIndirect(x, y);
}
#ifdef USE_REAL
void glDrawArraysIndirect(GLenum, const void*)
{
std::cout << "In real function" << std::endl;
}
#endif
int main()
{
wrapDraw(TEST, nullptr);
}
Include the expression sizeof(::function) somewhere. (If the function exists then asking for the size of the pointer to the function is a perfectly valid thing to do).
It will be benign at runtime, and :: forces the use of the function declared at global scope.
Of course, if function does not exist at global scope, then compilation will fail.
Along with other errors, the compiler will issue a specific error if you were to write something on the lines of
static_assert(sizeof(::function), "There is no global function");
My target operating system is very specific. Any linker based solution (like GetProcAddress or dlsym) doesn't work for me, since there is no dynamic linker.
Is this an embedded system or just a weirdly stripped down OS running on standard PC hardware?
More than, my driver doesn't provide glXGetProcAdrress nor wglGetProcAddress, basically there there is no way to query pointer at run time by function name
The abiliy to query function pointers at runtime does not depend on the presence of a dynamic linker. Those two are completely orthogonal and even a purely statically linked embedded OpenGL implementation can offer a GetProcAddress interface just fine. Instead of trying to somehow solve the problem at compile or link time, I'd rather address the problem by implementing a GetProcAddress for your OpenGL driver; you can do that even if the driver is available as only a static library in binary form. Step one:
Create function pointer stubs for each and every OpenGL function, statically initialized to NULL and attributed weak linkage. Link this into a static library you may call gl_null_stubs or similar.
Create a GetProcAddress function that for every OpenGL function there is returns the pointer to the function symbol within the scope of the function's compilation unit.
Now link your weird OpenGL driver with the stubs library and the GetProcAddress implementation. For every function there is, the weak linkage of the stub will the static library symbol to take precedence. For all OpenGL symbols not in your driver the stubs will take over.
There: Now you have a OpenGL driver library that has a GetProcAddress implementation. That wasn't that hard, was it?
How to check if function is declared in global scope at compile time?
My target operating system is very specific...
A possible solution might be, if you are using a recent GCC -probably as a cross-compiler for your weird target OS and ABI- to customize the gcc (or g++ etc...) compiler with your own MELT extension.
MELT is a domain specific language, implemented as a free software GCC plugin (mostly on Linux), to customize the GCC compiler.
I've project where I need to distinguish files belongs to linux daemon (witten in C) and simple linux program (written in C++). Those two projects used 2 shared files (helpers_functions). Daemon and program has different logging system. Daemon write to file, program to stdout.
Problem occurs when I want to log something in common functions for both programs (inside helper_functions file). I don't want to pass via parameter, that this is program A, or program B.
I've compile files belongs to separate programs with g++ flag -D, but what can I do, when I want to log from common files? I cannot define there anything, because I don't know when I use it for program A, or when for program B.
You could add a global variable
const int iamprogram = ...;
which is defined to be PROGRAM_A in program A and PROGRAM_B in program B to solve the immediate problem. You could also make this variable directly contain the file you want to log to:
const char *program_logfile = "/path/to/logfileA";
In the long run, I suggest you to refactor your code such that the common code doesn't depend on which program it is part of. That's much more maintainable and expandable for the case where you want to use the code for a third program as well.
I'm not 100% sure if runtime dynamic linking can handle this. It would definitely work if you statically link the helper functions into each executable.
Provide a logging function with the same API in both programs. Have the library functions that want to log something call this function. They get the implementation provided by the program that's using the library.
Header file included by each program, and by the library
// common_log.h
#ifdef __cplusplus
extern "C" // for the following definition only, no opening {
#endif
// used by code that can be part of either program
void common_log(char *msg, int log_prio);
Implementation in the tty C++ program (simple logging):
#include "common_log.h"
#include <iostream>
// used by the rest of the C++ program
void simple_logger(char *msg) {
cerr << msg;
}
extern "C" void common_log(char *msg, int log_prio) {
simple_logger(msg);
}
Implementation in the daemon C program:
#include "common_log.h"
#include <stdio.h>
#include <errno.h>
static FILE *logfp;
static int log_level;
// used by daemon code
void fancy_logger(char *msg, int log_prio) {
if (log_prio < log_level)
return;
if (EOF == fputs(logfp, msg)) {
perror("failed to write log message to log file: ");
}
}
// or use linker tricks to make common_log an alias for fancy_log,
// if they both have the same signature and you don't need to do anything in the wrapper.
//extern "C" // this is already C
void common_log(char *msg, int log_prio) {
fancy_logger(msg, log_prio);
}
This requires the linker to be able to resolve undefined symbols in the library using symbols from the program that's linked against it. I think that works, similar to a library providing a weak definition of a global variable, so the main program's definition takes precedence.
If it was ok for simple_logger to also be extern "C" and have the same signature, you could just name them the same and avoid the bounce function. Or if the common function could be an alias for the program's own logging function in either of the programs, I think there are linker tricks to actually do that, instead of compiling to a single jmp instruction (tail-call optimization).
You could implement a callback for getting the program specific output. There's two benefits: no dependency from common part to application (common part defines the interface) and you can make the distinction at run time vs compile time, which gives more legroom for future development, such as changing the output via command line parameters or user interaction.
In the following example, let's refer to the common code part as "library".
library.h
typedef void (*logFunc_t)( logBuffer_t );
void setLogOutput( logFunc_t applicationLog );
library.c
logFunc_t logger; // might be good idea to initialize to an empty function, but omitted here
void setLogOutput( logFunc_t applicationLog )
{
logger = applicationLog;
}
void log( logBuffer_t data )
{
logger( data );
}
application.cpp / application.c
// here you should have the extern "C" in C++ application to ensure linkage compatibility
// I am assuming your shared code is C
extern "C" void myLogger( logBuffer_t data );
int main( int argc, char* agv[] )
{
setLogOutput( &myLogger );
// ...do your thing
return 0;
}
void myLogger( logBuffer_t data )
{
// ...log wherever
}
I'm looking to implement a plugin architecture into our current application (Unix, C++) and have been reviewing the options (pending approval) within the Boost libraries.
Edit: I'm looking to dynamically add classes at runtime.
Boost.Plugin
Boost.Reflection
Boost.Extension
I was wondering what everyones experience/opinion is on these and other implementations.
Eh. We just used dlopen and dlsym along with a pair of extern "C" static functions that must be defined in the dll
extern "C" static plugin* create( arg_pack* );
extern "C" static errno_t destroy( plugin* );
Have a plugin-manager look for ".dll" or ".so" files and load them into a
map<string, pair< plugin*(*)(arg_pack*), errno_t(*)(plugin*)> >
You can then lookup a plugin based on a name (the string above) and get it's 'constructor' or 'destructor'
see also: gmodule
You can not load classes at run-time as C++ is a compiled language and classes do not exist at run-time. Objects (instances of classes) do.
What you can do is load shared libraries at run-time and make them create objects of a certain interface.
Minimal plug-in implementation would define the interface of your plug-in and the interface of the factory function that is going to create objects with that interface. You are going to load the shared library at run-time, find the factory function with a certain name, and call the factory function to create an object. Then you use that object though the interface:
// plugin.h start
#include <memory>
struct PlugIn // interface
{
virtual ~PlugIn() = 0;
virtual void doSomething() = 0;
};
extern "C" {
typedef std::auto_ptr<PlugIn> PlugInFactoryFn();
// A plugin .so must export this one factory function.
std::auto_ptr<PlugIn> createPlugIn();
}
// plugin.h end
// somewhere in you application
#include "plugin.h"
#include <assert.h>
#include <dlfcn.h>
std::auto_ptr<PlugIn> loadPlugIn(char const* filename)
{
void* so = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
assert(so);
void* factory_function = dlsym(so, "createPlugIn");
assert(factory_function);
return reinterpret_cast<PlugInFactoryFn*>(factory_function)();
}
int main()
{
std::auto_ptr<PlugIn> a(loadPlugIn("a.so"));
std::auto_ptr<PlugIn> b(loadPlugIn("b.so"));
a->doSomething();
b->doSomething();
}
I've spent days reading and re-reading every tutorials I've found on the subject, and spent hours (and even days) browsing related questions here at SO, but I still can't get the following to work. Accept my apologies if this is a duplicate: chances are that I've seen and re-read many times the duplicate questions but couldn't understand the relevance of the answers to my problem. With that out of the way...
I'm trying to implement a plugin architecture for my Application. Plugins are compiled and installed as libraries. At run time, the Application then uses dlopen() / dlsym() to load and link to the plugin's functions.
The idea is that plugins (libraries) will implement a set of functions to return data to the main Application, or manipulate data passed from the Application.
In order to test this idea, I tried to implement a function (inside the plugin) that would return the (human readable) name of the plugin itself (as a std::string). I thought that would be something simple to start with.... :-/
Here is what I got so far:
// Plugin.cpp
extern "C" void plugin_name(std::string *name) {
name = new std::string("Example plugin name");
}
// Application.cpp
void* handle = dlopen("libplugin.so", RTLD_LAZY);
typedef void (*plugin_t)(std::string*);
dlerror(); // Reset errors.
plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
// ... Some error handling code.
std::string my_plugin_name;
call_plugin_name(&my_plugin_name);
dlclose(handle);
// More code that displays my_plugin_name.
I've tried many different combinations, including one that seemed more straigtforward (but didn't work any better) where the plugin name is returned:
// Plugin.cpp
extern "C" std::string plugin_name(void) {
return std::string("Example plugin name");
}
I know I'm close: the code compiles and the Application stopped crashing ;)
However, I've got an empty space where I'd expect seeing the actual plugin name.
All the tutorials I've read so far go very quickly over the mechanism by which data is passed both ways: plugin <=> Application. What I'm trying to do with a "simple" std::string, I wish to do later with much more complex objects (i.e. a plugin function would take an object by reference and change some of its properties). The tutorials more or less all stop at the point of creating a pointer with dlsym() and do not give much examples on how to use this pointer.
So, how to do all that?
Another pertinent question: do I use a common header that I'd use both with the Application and with the plugin and where I'd define the function calls signature? How would I do this and how would that help?
The signature of a function is generated from its name and argument types (return value type doesn't matter). When you declare function with extern "C", C symbol naming scheme is used which apparently can't handle C++ types like std::string. That's why passing std::string as an arguments doesn't work.
I can't explain why returning std::string doesn't work. Maybe different calling conventions are used.
Anyway the correct way of importing C++ code from a shared library is to return pointers to C++ types from entry points. And this entry points have to have arguments with types available in C. (Entry point is a documented function exported from a shared library)
Here is a good article on basic aspects of loading C++ classes from shared libraries. This article will answer your question throughly.
Please note that there are pitfalls when using exceptions thrown from a shared library to the main applications. And with dynamic_cast of objects created inside a library. I've mentioned this topics so that you could be somewhat prepared when you face this problems.
[edit]
To make my answer more clear I'll add a couple of examples.
To get the plugin name you can use:
extern "C" const char * plugin_name() {
return "Example plugin name";
}
// main.cc:
void* handle = dlopen("libplugin.so", RTLD_LAZY);
// ...
typedef const char * (*plugin_t)();
plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
// ...
std::string my_plugin_name(call_plugin_name());
// use it
To really use the plugin functionality you should declare a base class in a header:
// plugin.h
class Plugin {
public:
virtual void doStuff() = 0;
virtual ~Plugin() = 0;
};
// plugin.cc
Plugin::~Plugin() {
}
// myplugin.cc
class MyPlugin : public Plugin {
virtual void doStuff() {
std::cout << "Hello from plugin" << std::endl;
}
};
extern "C" Plugin *createMyPluginInstance() {
return new MyPlugin;
}
Try:
extern "C" void plugin_name(std::string **name) {
*name = new std::string("Example plugin name");
}
...
std::string *my_plugin_name;
call_plugin_name(&my_plugin_name);
As you are assigning a copy of the pointer you passed as the argument, not the one you intended to assign.
EDIT Here you go:
File main.cpp
#include <iostream>
#include <dlfcn.h>
#include <string>
// Application.cpp
int main() {
void* handle = dlopen("libplugin.so", RTLD_LAZY);
typedef void (*plugin_t)(std::string**);
dlerror(); // Reset errors.
plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
// ... Some error handling code.
std::string *my_plugin_name;
call_plugin_name(&my_plugin_name);
dlclose(handle);
// More code that displays my_plugin_name.
std::cout << "Plugin name is " << *my_plugin_name << std::endl;
delete my_plugin_name;
return 0;
}
File plugin.cpp
#include <string>
extern "C" void plugin_name(std::string **name) {
*name = new std::string("example plugin name");
}
Just a word of warning. Although this compiles and runs, passing C++ types across the dll boundry is risky and the above code is just your code fixed enough to compile and run, it is not safe and has very explicit memory handling. You may want to attack the problem in a different way.
Please have a read of this question and its answers. There are many opportunities for incompatibilities across the shared lib boundaries in C++.