How to initialize a shared library on Linux - c++

I am developing a shared library using C++ under Linux, and I would like this library to use log4cxx for logging purposes. However, I'm not sure how to set this up. For log4cxx to work, I need to create a logger object. How can I make sure this object is created when my library is loaded?
I suspect that it will be easiest to create the logger object as a global variable and then use it from any of the source files of my library, declaring it as extern in the headers. But how can I have the logger created automatically once an application connects to the library?
I know that in DLLs for Windows, there's a thing as REASON_FOR_CALL == PROCESS_ATTACH; is there a similar thing under Linux?

In C++ under Linux, global variables will get constructed automatically as soon as the library is loaded. So that's probably the easiest way to go.
If you need an arbitrary function to be called when the library is loaded, use the constructor attribute for GCC:
__attribute__((constructor)) void foo(void) {
printf("library loaded!\n");
}
Constructor functions get called by the dynamic linker when a library is loaded. This is actually how C++ global initialization is implemented.

If you want your code to be portable you should probably try something like this:
namespace {
struct initializer {
initializer() {
std::cout << "Loading the library" << std::endl;
}
~initializer() {
std::cout << "Unloading the library" << std::endl;
}
};
static initializer i;
}

Using a global (or a local-static wrapped up in a function) is nice... but then you enter the land of static initialization fiasco (and the actual destruction is not pretty either).
I would recommend to have a look at the Singleton implementation of Loki.
There are various lifetime policies, one of which is Phoenix and will help you avoid this fiasco.
When you are at it, read Modern C++ Design which explains the problems encountered by the Singleton in depth as well as the uses for the various policies.

Related

At runtime, when is the std library completely initialized for it to be used without breaking the code?

I am working on a project which includes startup code prior to the call to main. I am however unaware of the std library initializations.
I know that the following code will throw a segmentation fault.
#include <iostream>
void foo(void) __attribute__((constructor));
void foo() {
std::cout << "foo" << std::endl;
}
int main() {
std::cout << "Simple program to throw a segmentation fault" << std::endl;
}
The above code can be made to work by force initializing the ostream buffer (not sure if it's exactly ostream) by using std::ios_base::Init mInitializer;. This would mean that the std library was not completely initialized at this point (that is my inference of the above example).
So when can I use std functions without actually breaking the code? Is there a way to force initialize complete std library?
The documentation for the constructor attribute says this:
However, at present, the order in which constructors for C++ objects with static storage duration and functions decorated with attribute constructor are invoked is unspecified.
This means that ELF constructors and static objects (as the one used for initialization of std::cout) do not mix well.
On the other hand, std::cout is a historical exception because it does not rely on a constructor in the C++ standard library. On ELF systems, ELF constructors run in topological order. This means that the dynamic linker looks at the library dependencies (the DT_NEEDED entries) and delays initialization of libraries before their dependencies are initialized.
As a result, C++ code can assume that the C++ run-time library is fully initialized when ELF constructors run and global objects defined by the application are constructed. The only exception is a C++ library which preempts routines used by the standard C++ standard library itself (via ELF symbol interposition), and if there are cyclic dependencies among the libraries, so that there is no correct initialization order. Both cases are not common, and unless you write a custom malloc or something like that, can be avoid with proper application design.

I can not get an execute-on-load function to work in a library using Qt

I have several libraries, each of which implement a class (derived from QObject). I would like each of these libraries to execute a function the first time they load. I found a couple of similar questions here:
Automatically executed functions when loading shared libraries
and
How exactly does __attribute__((constructor)) work?
but any initialization function I create based on the answers never executes. I've tried creating the function in a namespace, outside a namespace (and not a part of my class), using __attribute__((constructor)), naming it _init, and specifying the function name to the linker with:
QMAKE_LFLAGS_RELEASE += -Wl,-init,libinitfunc
None of these have worked.
I should also note that I'm cross-compiling these libraries to run on an embedded ARM device that uses busybox for much of its functionality.
Since this is C++ code, you shouldn't need C-style hacks.
class LibInstance {
public:
LibInstance() {
qDebug() << __FILE__ << "has been initialized";
}
~LibInstance() {
qDebug() << __FILE__ << "has been unloaded";
}
}
Q_GLOBAL_STATIC(LibInstance, libInstance)
class LibExecutor {
LibExecutor() { libInstance(); }
};
static LibExecutor libExecutor;
An instance of LibExecutor is guaranteed to be constructed, in a non-threadsafe way, before main() starts running; or before the library finishes loading, if it's demand-loaded. The LibExecutor's constructor is then using the Q_GLOBAL_STATIC implementation to thread-safely execute the LibInstance's constructor.
It is in LibInstance's constructor that you place the initialization functionality you desire. The destructor will be called when the library is being unloaded.
It is generally safe, cross platform, and used within Qt itself.

Keeping the structure of a shared libraries plug-in system when compiling statically and linking

For the C++ library I am currently developing I have seen the advantages of a plug-in system based on shared libraries. A feature will become available to the user of the library just if one of the shared libraries that are in a directory scanned at initialization time is offering that.
Using dlopen, the shared libraries will be searched for two symbols: one function that returns the string that names the feature they implement, and a create function that instantiates the class and returns a pointer to the basse class. Something like this:
In Library A
#include "Instance.hpp"
extern "C" const char* type() {
return "InstanceA";
}
//... class InstanceA definition, inherits from Instance
extern "C" Instance* create() {
return new InstanceA();
}
The Core library will scan the plug-ins directory and keep a map string->pointerToCreateFunction in order to create new instances.
This is really handy, and a pretty standard thing to do. If the user code tries to instantiate an InstanceX but no shared library implement that type, an error will be given, everything will work perfectly.
But this framework will be used also for iOs development, and the App Store doesn't allow loading 3rd party shared objects. I would like to keep this modular plug-in structure even when loading a self contained version of the library that links statically the plugins. Note that at project management level this would be as easy as defining a variable in CMake that creates static versions of the plugins and links them statically. This would also exclude the dynamic loading part of the code.
What I am missing is how to invert the mechanism: while for shared objects the core library will leverage on the file system to learn about the possible type of instances that can be used, I don't know how to "register" them without changing big part of the code, and without going in the static initialization fiasco. Looks like the only way to have that is subsituting the code that scans the types and the create function by including all the possible headers and having a big switch like
Instance* theInstance;
if (instanceRequired == "instanceA")
theInstance = new InstanceA();
etc etc...
Do you have any thought on a way to avoid including all the headers and having to change the code in Core each time a new instance is added?
I do such things through those pesky static objects that call register in ctor.
The ordering problem is dodged by making the map itself a local static, so getting constructed on the first client call, wherever it comes from. (Threading and similar issues are dodged by restricting thread launch to until-main time, and by that time all important things are forced.)
class RegMap; // the registry
RegMap& GetRegistry(); // the singleton access function; you can make a separate const/nonconst version or provide another wrapper for registering
// implementation in core.cpp:
RegMap& GetRegistry()
{
static RegMap m;
return m;
}
//in client ctor:
GetRegistry().Register( key, func);

Static linking of C++ code

I have the following problem: I use some classes like the following to initialize C libraries:
class Hello
{
public:
Hello()
{
cout << "Hello world" << endl;
}
~Hello()
{
cout << "Goodbye cruel world" << endl;
}
} hello_inst;
If I include this code in a hello.cc file and compile it together with another file containing my main(), then the hello_inst is created before and destroyed after the call
to main(). In this case it just prints some lines, in my project I initialize libxml via
LIBXML_TEST_VERSION.
I am creating multiple executables which share a lot of the same code in a cmake project.
According to this thread: Adding multiple executables in CMake I created a static library containing the code shown above and then linked the executables against that library. Unfortunately in that case the hello_inst is never created (and libxml2 is never initialized). How can I fix this problem?
I had a similar problem and solved it by defining my libraries as static. Therefore I used the following code:
add_library( MyLib SHARED ${LBMLIB_SRCS} ${LBMLIB_HEADER})
Maybe this fixes your problem
There is no official way of forcing shared libraries global variables to be initialised by the standard and is compiler dependent.
Usually this is done either the first time something in that library is actually used (A class, function, or variable) or when the variable itself is actually used.
If you want to force hello_inst to be used, call a function on it, then see if and when the constructor and destructors are called.
Read this thread for more information:
http://www.gamedev.net/topic/622861-how-to-force-global-variable-which-define-in-a-static-library-to-initialize/
As far as I'm aware, statics defined in library should be constructed before main is called and destroyed after main, in the manner you describe. Indeed I have used shared libraries in many projects, and have never encountered the problems you describe.
I understand a library file, to be little more than a container of object files.
However, that said.....
If your code does nothing with the object that is created, the linker is free to remove it (dead code removal). I would suggest making sure the static object is referenced. Call a member function, perhaps?

Explicit Loading of DLL

I'm trying to explicitly link with a DLL. No other resources is available except the DLL file itself and some documentation about the classes and its member functions.
From the documentation, each class comes with its own
member typedef
example: typedef std::map<std::string,std::string> Server::KeyValueMap, typedef std::vector<std::string> Server::String Array
member enumeration
example: enum Server::Role {NONE,HIGH,LOW}
member function
example: void Server::connect(const StringArray,const KeyValueMap), void Server::disconnect()
Implementing the codes from google search, i manage to load the dll can call the disconnect function..
dir.h
LPCSTR disconnect = "_Java_mas_com_oa_rollings_as_apiJNI_Server_1disconnect#20";
LPCSTR connect =
"_Java_mas_com_oa_rollings_as_apiJNI_Server_1connect#20";
I got the function name above from depends.exe. Is this what is called decorated/mangled function names in C++?
main.cpp
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "dir.h"
typedef void (*pdisconnect)();
int main()
{
HMODULE DLL = LoadLibrary(_T("server.dll"));
pdisconnect _pdisconnect;`
if(DLL)
{
std::cout<< "DLL loaded!" << std::endl;
_disconnect = (pdisconnect)GetProcAddress(DLL,disconnect);
if(_disconnect)
{
std::cout << "Successful link to function in DLL!" << std::endl;
}
else
{
std::cout<< "Unable to link to function in DLL!" << std::endl;
}
}
else
{
std::cout<< "DLL failed to load!" << std::endl;
}
FreeLibrary (DLL);
return 0;}
How do i call (for example) the connect member function which has the parameter datatype declared in the dll itself?
Edit
more info:
The DLL comes with an example implementation using Java. The Java example contains a Java wrapper generated using SWIG and a source code.
The documentation lists all the class, their member functions and also their datatypes. According to the doc, the list was generated from the C++ source codes.(??)
No other info was given (no info on what compiler was used to generate the DLL)
My colleague is implementing the interface using Java based on the Java example given, while I was asked to implement using C++. The DLL is from a third party company.
I'll ask them about the compiler. Any other info that i should get from them?
I had a quick read through about JNI but i dont understand how it's implemented in this case.
Update
i'm a little confused... (ok, ok... very confused)
Do i call(GetProcAddress) each public member function separately only when i want to use them?
Do i create a dummy class that imitates the class in the dll. Then inside the class definition, i call the equivalent function from the DLL? (Am i making sense here?) fnieto, is this what you're showing me at the end of your post?
Is it possible to instantiate the whole class from the DLL?
I was trying to use the connect function described in my first post. From the Depends.exe DLL output,
std::map // KeyValueMap has the following member functions: del, empty, get, has_1key,set
std::vector // StringArray has the following member functions: add, capacity, clear, get, isEMPTY, reserve, set, size
which is different from the member functions of map and vector in my compiler (VS 2005)...
Any idea? or am i getting the wrong picture here...
Unless you use a disassembler and try to figure out the paramater types from assemly code, you can't. These kind of information is not stored in the DLL but in a header file coming with the DLL. If you don't have it, the DLL is propably not meant to be used by you.
I would be very careful if I were you: the STL library was not designed to be used across compilation boundaries like that.
Not that it cannot be done, but you need to know what you are getting into.
This means that using STL classes across DLL boundaries can safely work only if you compile your EXE with the same exact compiler and version, and the same settings (especially DEBUG vs. RELEASE) as the original DLL. And I do mean "exact" match.
The C++ standard STL library is a specification of behavior, not implementation. Different compilers and even different revisions of the same compiler can, and will, differ on the code and data implementations. When your library returns you an std::map, it's giving you back the bits that work with the DLL's version of the STL, not necessarily the STL code compiled in your EXE.
(and I'm not even touching on the fact that name mangling can also differ from compiler to compiler)
Without more details on your circumstances, I can't be sure; but this can be a can of worms.
In order to link with a DLL, you need:
an import library (.LIB file), this describes the relation between C/C++ names and DLL exports.
the C/C++ signatures of the exported items (usually functions), describing the calling convention, arguments and return value. This usually comes in a header file (.H).
From your question it looks like you can guess the signatures (#2), but you really need the LIB file (#1).
The linker can help you generate a LIB from a DLL using an intermediate DEF.
Refer to this question for more details: How to generate an import library from a DLL?
Then you need to pass the .lib as an "additional library" to the linker. The DLL must be available on the PATH or in the target folder.