Make local c library function accessable globally - c++

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

Related

Obtaining filename at runtime for a shared library 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;
}

error when using extern "C" to include a header in c++ program

I am working on a school project which requires to work with sheepdog. Sheepdog provides a c api which enables you to connect to a sheepdog server.
First i create c source file(test.c) with the following content :
#include "sheepdog/sheepdog.h"
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
fprintf(stderr, "failed to connect %m\n");
return -1;
}else{
fprintf(stderr, "connected successfully %m\n");
}
return 0;
}
then i compile with no error using the following command
gcc -o test test.c -lsheepdog -lpthread
But what i need is to use it with c++ project so i created a cpp file(test.cpp) with the following content :
extern "C"{
#include "sheepdog/sheepdog.h"
}
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
fprintf(stderr, "failed to connect %m\n");
return -1;
}else{
fprintf(stderr, "connected successfully %m\n");
}
return 0;
}
now, when i compiled using the following command :
g++ -o test test.cpp -lsheepdog -lpthread
I got this error :
You can't just wrap extern "C" around a header and expect it to compile in a C++ program. For example, the header sheepdog_proto.h uses an argument named new; that's a keyword in C++, so there's no way that will compile as C++. The library was not designed to be called from C++.
I agree with #PeteBecker. From a quick look around Google, I am not sure there is an easy solution. Sheepdog is using C features and names that don't port well to C++. You might need to hack sheepdog fairly extensively. For example:
move the inline functions out of sheepdog_proto.h into a new C file, leaving prototypes in their place. This should take care of the offsetof errors, e.g., discussed in this answer.
#define new not_a_keyword_new in sheepdog/sheepdog.h
and whatever other specific changes you have to make to get it to compile. More advice from the experts here.
As sheepdog was not designed to be useable from C++ you should build a tiny wrapper in C language to call the functions from sheepdog and only call the wrapper from your c++ code. Some hints to write such a wrapper:
void * is great to pass opaque pointers
extractors can help to access badly named members. If a struct has a member called new (of type T), you could write:
T getNew(void *otherstruct); // declaration in .h
and
T getNew(void *otherstruct) { // implementation in a c file
return ((ActualStruct *) otherstruct)->new;
}
Depending on the complexity of sheepdog (I do not know it) and the part you want to use, it may or not be an acceptable solution. But it is the way I would try facing such a problem.
Anyway, the linker allows mixing modules compiled in C and in C++, either in static linking or dynamic linking.

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
}

How to use dlsym reliably when you have duplicated symbols?

Good evening, I'm currently working on a Plugin system in C++/Linux based on the Plux.net model.
To keep it simple, I basicly declare a symbol (lets call it pluginInformation) with extern C (to unmangle) and my plugin manager look for that symbol in the pre configured imports (.so).
The thing is that the main application declares the same symbol, not only that but any dependency it have may have the symbol aswell. (since in this pluginInformation, modules can publish plugs and/or slots).
So when my PluginManager starts, it first try to find the symbol in the main program (passing NULL to dlopen), then it tries to find the symbol in any of its dependencies (using dl_iterate_phdr). And last it will dlopen a set of configure imports (it will read the path of the .so that the user configured, dlopen them and finally dlsym the pluginInformation symbol).
The collection of pluginInformation found in all the modules is used then to build the extension three.
If I declare the symbol in the main program and load the imports using dlopen, it works (as long as I pass the flag RTLD_DEEPBIND when dlopening the imports).
But for the application dependencies I dont have the option of passing the flag (I can but it doesnt do anything) since this .sos were loaded at the start up of the application.
Now when I try to use any of the symbols I got from the dependencies (the ones loaded at start up) I get a segmentation fault. I assume the problem is that I have several symbols with the same name in the symbol table, the weird thing is that it seems to correctly identify that there are several symbols and it even gives me the correct path of the .so where the symbol is declared, but as soon as I access the symbol a segmentation fault occurs. If I only declare the symbol in the main program or in one of the dependencies everything works correctly.
How can I manage duplicate symbols between the main program and the strat up imports with dlsym?.
I have been thinking in keep the mangling and then just try to find my symbol pasring the symbol table, but im not sure this is even possible (listing all the symbols in a module programmatically).
PD: Sorry I didnt post any code, but im not at home right now, I hope the description of what im trying to do is clear enough, if not I can post some code tomorrow.
Here is an alternate approach.
The application itself exports one or more plugin item registration functions. For example:
int register_plugin_item(const char *const text,
const char *const icon,
void (*enter)(void *),
void (*click)(void *),
void (*leave)(void *),
void *data);
Per registered item, there are two string slots (text and icon), three function slots (enter, click, and leave), and an opaque reference that is given to the functions as a parameter when called.
(Note that you'll need to use the -rdynamic compiler option when compiling the main application (the object file implementing the above function), to make sure the linker adds the register_plugin_item symbol to the dynamic symbol table.)
Each plugin calls the register_plugin_item() function for each of the items it wants, in a constructor function (that is automatically run at library load time). It is possible, and often useful, for the function to first examine the environment it runs in to determine which features to register, or which optimized variants of functions to use for each plugin item.
Here is a trivial example plugin. Note how all the symbols are static, so that the plugin does not pollute the dynamic symbol table, or cause any symbol conflicts.
#include <stdlib.h>
#include <stdio.h>
extern int register_plugin_item(const char *const,
const char *const,
void (*enter)(void *),
void (*click)(void *),
void (*leave)(void *),
void *);
static void enter(void *msg)
{
fprintf(stderr, "Plugin: Enter '%s'\n", (char *)msg);
}
static void leave(void *msg)
{
fprintf(stderr, "Plugin: Leave '%s'\n", (char *)msg);
}
static void click(void *msg)
{
fprintf(stderr, "Plugin: Click '%s'\n", (char *)msg);
}
static void init(void) __attribute__((constructor));
static void init(void)
{
register_plugin_item("one", "icon-one.gif",
enter, leave, click,
"1");
register_plugin_item("two", "icon-two.gif",
enter, leave, click,
"2");
}
The above plugin exports two items. For testing, create at least a couple of variants of the above; you will see that there are no symbol conflicts even if the plugins use same (static) variables and function names.
Here is an example application that loads the specified plugins, and tests each registered item:
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
struct item {
struct item *next;
const char *text;
const char *icon;
void *data;
void (*enter)(void *);
void (*leave)(void *);
void (*click)(void *);
};
static struct item *list = NULL;
int register_plugin_item(const char *const text,
const char *const icon,
void (*enter)(void *),
void (*click)(void *),
void (*leave)(void *),
void *data)
{
struct item *curr;
curr = malloc(sizeof *curr);
if (!curr)
return ENOMEM;
curr->text = text;
curr->icon = icon;
curr->data = data;
curr->enter = enter;
curr->leave = leave;
curr->click = click;
/* Prepend to list */
curr->next = list;
list = curr;
return 0;
}
int main(int argc, char *argv[])
{
int arg;
void *handle;
struct item *curr;
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s PLUGIN.so ... \n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "Please supply full plugin paths, unless\n");
fprintf(stderr, "the plugins reside in a standard library directory,\n");
fprintf(stderr, "or in a directory listed in LD_LIBRARY_PATH.\n");
fprintf(stderr, "\n");
return 1;
}
for (arg = 1; arg < argc; arg++) {
handle = dlopen(argv[arg], RTLD_NOW);
if (handle != NULL)
fprintf(stderr, "%s: Loaded.\n", argv[arg]);
else
fprintf(stderr, "%s.\n", dlerror());
/* Note: We deliberately "leak" the handle,
* so that the plugin is not unloaded. */
}
for (curr = list; curr != NULL; curr = curr->next) {
if (curr->text)
printf("Item '%s':\n", curr->text);
else
printf("Unnamed item:\n");
if (curr->icon)
printf("\tIcon is '%s'\n", curr->icon);
else
printf("\tNo icon\n");
if (curr->data)
printf("\tCustom data at %p\n", curr->data);
else
printf("\tNo custom data\n");
if (curr->enter)
printf("\tEnter handler at %p\n", curr->enter);
else
printf("\tNo enter handler\n");
if (curr->click)
printf("\tClick handler at %p\n", curr->click);
else
printf("\tNo click handler\n");
if (curr->leave)
printf("\tLeave handler at %p\n", curr->leave);
else
printf("\tNo leave handler\n");
if (curr->enter || curr->click || curr->leave) {
printf("\tTest calls:\n");
if (curr->enter)
curr->enter(curr->data);
if (curr->click)
curr->click(curr->data);
if (curr->leave)
curr->leave(curr->data);
printf("\tTest calls done.\n");
}
}
return 0;
}
If the application is app.c, and you have plugins plugin-foo.c and plugin-bar.c, you can compile them using e.g.
gcc -W -Wall -rdynamic app.c -ldl -o app
gcc -W -Wall -fpic -c plugin-foo.c
gcc -shared -Wl,-soname,plugin-foo.so plugin-foo.o -o plugin-foo.so
gcc -W -Wall -fpic -c plugin-bar.c
gcc -shared -Wl,-soname,plugin-bar.so plugin-bar.o -o plugin-bar.so
and run using e.g.
./app --help
./app ./plugin-foo.so
./app ./plugin-foo.so ./plugin-bar.so
Note that if the same plugin is defined more than once, the constructor is only executed once for that library. There will be no duplicate registrations.
The interface between the plugins and the application is completely up to you. In this example, there is only one function. A real application would probably have more. The application can also export other functions, for example for the plugin to query application configuration.
Designing a good interface is a whole different topic, and definitely deserves at least as much thought as you put in the implementation.
The Plux.NET plugin platform allows plugins to export their own slots, too. This alternate approach allows that in many ways. One of them is to export a plugin registration function -- that is, for registering plugins instead of individual items -- that takes a function pointer:
int register_plugin(const char *const name,
int (*extend)(const char *const, ...));
If the plugin provides slots, it provides its own registration function as the extend function pointer. The application also exports a function, for example
int plugin_extend(const char *const name, ...);
that the plugins can use to call other plugins' registration functions. (The implementation of plugin_extend() in the main application involves searching for a suitable extend function already registered, then calling it/them.)
Implementation-wise, allowing plugins to export slots complicates implementation quite a bit. In particular, when and in which order should the slots exported by the plugins become available? Is there a specific order in which plugins must be loaded, to make sure all possible slots are exported? What happens if there is a circular dependency? Should plugins specify which other plugins they rely on before the registrations commence?
If each plugin is a separate entity that does not export any slots of its own, only plugs into main application slots, you avoid most of the complexity in the implementation.
The order in which registered items are examined is a detail you probably need to think about, though. The above example program uses a linked list, in which the items end up in reverse order compared to the registration order, and registration order is the same as the order in which the plugin file names are first specified on the command line. If you have a plugin directory, which is automatically scanned (using e.g. opendir()/readdir()/dlopen()/closedir() loop), then the plugin registration order is semi-random (depending on the filesystem; usually changing only when plugins are added or removed).
Corrections? Questions? Comments?

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.