This was created using Code::Blocks; I dunno why, but I find this IDE easier to use than Eclipse or NetBeans for hobby coding.
First, lets create that header file that describes the standard interfaces and functions.
vo.h
// Ensure the programmer doesn't import our declarations twice.Just to help us visualise what is happening, let's create the implementation of our header. Nothing too complex... all we will do is return the internal state of a global variable (yes this is not good practice, but it's just for show).
// This also stops name conflicts from occurring early on.
#ifndef VO_H
#define VO_H
// Prevent the c++ compiler from corrupting names
// and creating "unresolved symbols" when linking
#ifdef __cplusplus
extern "C" {
#endif
// Standard initiliaser
int init( void );
#ifdef __cplusplus
}
#endif
#endif
vo.cpp
// Import local librariesNow we can compile our shared library. Code::Blocks allowed me to create a project with settings to automatically do this for me, but for those using something different this is the command to run (make sure you do so inside the directory that stores the source code!!):
#include "voNameGen.h"
// use the std namespace as the default
using namespace std;
bool bInit = false;
int init( void )
{
return bInit;
}
g++ -fPIC -shared vo.cpp -o libVo.so
So now we have our shared library object. Let's have a quick look inside with nm. This tool shows the symbols inside our library, which are used by other programs to 'hook' into our code. After running the command, you will notice our function, init, is at the bottom of the list. This is the 'hook' we are going to use...
nm -d libVo.so
Now let's use our library!!
testrig.c
There is nothing more I can really add to this; just go through the code and read the comments! To compile this code manually just type in (the -ldl flag is important as it tells the compiler to use the dlfcn library):
// Libraries for input and output#include <stdio.h>#include <iostream>// Library for dynamic linking#include <dlfcn.h>// Make sure this points to our// standard header file!!!!#include "vo.h"// Use the standard namespace// Change only if you know what// you are doing!!using namespace std;int main(){// This will hold our reference// to our library...void *lib_handle;// This is our prototype function// for init... note the asterixes// (Learn about pointers before// changing!!!)int* (*init)();// Hold out error codechar *error;// Using iostream to create outputcout << "Hello world!" << endl;// Opening up our shared librarylib_handle = dlopen("libVo.so", RTLD_LAZY);// If the library failed to open, exitif (!lib_handle){// This uses stdlib to create outputfprintf(stderr, "%s\n", dlerror());return 1;}// Point our function to the address of our desired// function located in the library....init = (int* (*)())dlsym(lib_handle, "init");// If we failed to find the function, exitif ((error = dlerror()) != NULL){// This uses stdlib to create outputfprintf(stderr, "%s\n", error);return 1;}// Execute the function in the library// and pipe the output directly to the// command linecout << fn() << endl;// Close our library and save memorydlclose(lib_handle);// Exit the programreturn 0;}
g++ -ldl main.cpp -o main
UPDATE: It has been noticed in the comments that "g++ main.cpp -ldl -o main" works instead of "g++ -ldl main.cpp -o main". Keep this in mind in case you come across any errors.
Now just make sure libVo.so is in the same directory as main before you execute it!
References
A Stack Overflow discussion on the topic
The YoLinux tutorial on the topic of libraries
what might the cause of this be?
ReplyDeletetestrig.c:(.text+0x3d): undefined reference to `dlopen'
testrig.c:(.text+0x4d): undefined reference to `dlerror'
testrig.c:(.text+0x82): undefined reference to `dlsym'
testrig.c:(.text+0x8b): undefined reference to `dlerror'
testrig.c:(.text+0xcb): undefined reference to `dlclose'
thankyou
tobias
seems "g++ main.cpp -ldl -o main" instead of "g++ -ldl main.cpp -o main" did the trick. thanks for the tutorial man
Deleteno problems... I have updated the tutorial to note this.
DeleteI also have noticed that some of my code got jumbled up since I have updated the layout. I am surprised you managed to make sense of it! Should be fixed now...