Obtaining filename at runtime for a shared library c++ - c++

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;
}

Related

How to distinguish files of two separate programs with common file

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
}

Make local c library function accessable globally

I'm using a C library called GLC to record my OpenGL buffer programmatically.
GLC listens to key presses, which is not really a nice solution to trigger programmatically.
Therefore I want to execute the recording from GLC via a function call in my software.
My C++ software is linking to the library which includes the desired function start_capture(). Via nm I can see this function is local, marked with a lower case t.
Since it has to be global to access it in my software I want to recompile the library (which I've already done). But I have no idea what to change to make it accessible....
Here is the declaration from start_capture(), in the header file lib.h
...
__PRIVATE int start_capture(); // No idea where the __PRIVATE is coming from
...
This is the definition/implementation of the start_capture() function in the main.c:
int start_capture()
...
return ret;
}
And this is my dlopen to get the function:
void *handle_so;
void (*start_capture_custom)();
char *error_so;
handle_so = dlopen("/home/jrick/fuerte_workspace/sandbox/Bag2Film/helper/libglc-hook.so", RTLD_LAZY);
if (!handle_so)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
dlerror(); /* Clear any existing error */
start_capture_custom = (void (*)())dlsym(handle_so, "start_capture");
if ((error_so = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error_so);
exit(1);
}
start_capture_custom();
dlclose(handle_so);
start_capture();
So what am I supposed to change to access this via the library file?
I hope this was enough description to make the problem clear. If not, I'll answer as fast as I can.
__PRIVATE is a #define for a GCC extension to hide a symbol. See https://github.com/nullkey/glc/blob/master/src/glc/common/glc.h#L60 for the definition and http://gcc.gnu.org/wiki/Visibility for more info about the GCC extension.
https://stackoverflow.com/a/12011284/2146478 provides a solution that will unhide symbols without recompiling. You would want to do something like:
$ objcopy --globalize-symbol=start_capture /path/to/your/lib.a /path/to/new/lib.a

How to manipulate/return data with dynamically loaded functions (dlopen)?

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++.

How do I load a shared object in C++?

I have a shared object (a so - the Linux equivalent of a Windows dll) that I'd like to import and use with my test code.
I'm sure it's not this simple ;) but this is the sort of thing I'd like to do..
#include "headerforClassFromBlah.h"
int main()
{
load( "blah.so" );
ClassFromBlah a;
a.DoSomething();
}
I assume that this is a really basic question but I can't find anything that jumps out at me searching the web.
There are two ways of loading shared objects in C++
For either of these methods you would always need the header file for the object you want to use. The header will contain the definitions of the classes or objects you want to use in your code.
Statically:
#include "blah.h"
int main()
{
ClassFromBlah a;
a.DoSomething();
}
gcc yourfile.cpp -lblah
Dynamically (In Linux):
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("libm.so", RTLD_LAZY);
if (!handle) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
dlerror(); /* Clear any existing error */
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
return 0;
}
*Stolen from dlopen Linux man page
The process under windows or any other platform is the same, just replace dlopen with the platforms version of dynamic symbol searching.
For the dynamic method to work, all symbols you want to import/export must have extern'd C linkage.
There are some words Here about when to use static and when to use dynamic linking.
It depends on the platform. To do it at runtime, on Linux, you use dlopen, on windows, you use LoadLibrary.
To do it at compile time, on windows you export the function name using dllexport and dllimport. On linux, gcc exports all public symbols so you can just link to it normally and call the function. In both cases, typically this requires you to have the name of the symbol in a header file that you then #include, then you link to the library using the facilities of your compiler.
You need to #include any headers associated with the shared library to get the declrarations of things like ClassFromBlah. You then need to link against the the .so - exactly how you do this depends on your compiler and general instalation, but for g++ something like:
g++ myfile.cpp -lblah
will probably work.
It is -l that link the archive file like libblah.a or if you add -PIC to gcc you will get a 'shared Object' file libblah.so (it is the linker that builds it).
I had a SUN once and have build this types of files.
The files can have a revision number that must be exact or higher (The code can have changed due to a bug). but the call with parameters must be the same like the output.

How to use 2 C libs that export the same function names [duplicate]

This question already has answers here:
Closed 13 years ago.
Duplicate of the following question: C function conflict
Hi,
in my current project I have to use some kind of interface lib. The function names are given by this interface, what this functions do is developers choice. As far as I can tell a project shall use this functions and when it comes to compiling you choose the lib and with it the functionality. What I try to do is to use an existing lib and my lib at the same time by wrapping the other and call it in mein functions:
otherlib:
int function1 (int a) {
// do something
}
mylib:
int function1 (int a) {
//my code here
otherlib::function1(a);
}
Problem is I don't have access to the other lib and the other lib doesn't have any namespaces. I already tried
namespace old {
#include "otherlib.h"
}
and then call the old function by old::function1 in my function. This works as long as it's only header file. The lib exports it's symbol back into global space. Also something like
namespace new {
function1 (int a) {
::function1(a);
}
}
didn't work. Last but not least I tried ifdefs and defines suggested here
but I wasn't successful.
Any ideas how to solve this? Thanks in advance.
EDIT: I neither have access to the old lib nor the project both libs shall be used in.
EDIT2: at least the old lib is a static one
Namespaces in C solved using library names prefixes like:
libfoo --> foo_function1
libbar --> bar_function1
These prefixes are actual namespaces. so if you write libbar
int bar_function1(int a) {
function1(a);
}
This is the way to solve problems.
C has namespaces --- they just called prefixes ;)
Another option is to do various dirty tricks with dynamic loading of libraries like:
h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")
h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")
It seems as if the other lib is C and your code is C++. You can be running into a mangling problem (C++ compilers mangle the symbols -- add extra stuff in the symbol name do differentiate overloads and the like).
If the library is pure C you can try:
extern "C" { // disable mangling of symbol names in the block
#include "otherlib.h"
}
namespace new_lib { // new is a reserved word
int function1( int a ) {
::function1(a);
}
}
I have not tried it. Also consider providing the error messages you are getting.
Another option would be (if the library is dynamic) dynamically loading the lib and calling the function. In linux (I don't know about windows) you can use dlopen to open the library, dlsym to obtain the symbol and call it:
// off the top of my head, not tried:
int function1( int a )
{
int (*f)(int); // define the function pointer
void * handle = dlopen( "library.so" );
f = dlsym( handle, "function1" );
f( a ); // calls function1(a) in the dynamic library
}
In this case, as you are not linking against the library you won't get a symbol conflict, but then again, it is only valid for dynamic libraries and it is quite cumbersome for regular usage.
UPDATE
If your users will not use 'otherlib' directly (they won't include their headers) and they will be only C++, then the first approach could be possible (even if horrible to read):
// newlib.h
namespace hideout {
int f( int a );
}
using namespace hideout; // usually I would not put this on the header
// newlib.cpp
extern "C" { // if otherlib is C, else remove this line
#include "otherlib.h"
}
namespace hideout {
int f( int a ) { return ::f( a*2 ); }
}
// main.cpp
#include "newlib.h"
int main()
{
std::cout << f( 5 ) << std::endl;
}
How does it work? User code will only see a declaration of function1 (in the example f()) as they are not including otherlib.h. Inside your compilation unit you see the two declarations but you differentiate through the use of the namespace. The using statement in the header does not bother you as you are fully qualifying in your cpp. The user main.cpp will include only your header, so the compiler will only see hideout::f, and will see it anywhere due to the using statement. The linker will have no problem as the C++ symbol is mangled identifying the real namespace:
// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1
If user code will include both your header and otherlib.h then it will have to qualify which function it wants to call.
If you're really desperate, you could write a wrapper library that uses namespaces or prefixes or allows for the dlsym trick. This wrapper library would need to be dynamically linked (to avoid symbol conflicts). The dynamic library could then safely have the old static library embedded in it. Just make sure you don't export the symbols from the static library when making the dynamic wrapper library.
You can't resolve this at link time, so you'll need to resolve it at runtime via dynamic libraries. The symbol for those functions is essentially baked it once the library has been generated. If two libraries export the same symbol, they cannot both be linked with statically.