参考文档
Dynamic Library Programming
linphone AudioTrack
cpp class demo
/* File: Person.cpp */
#include <iostream>
#include "Person.h"
#define EXPORT __attribute__((visibility("default")))
EXPORT Person::Person() {
char default_name[] = "<no value>";
this->set_name(default_name);
}
EXPORT Person::Person(char *name) {
this->set_name(name);
}
EXPORT Person::~Person() {
printf("~Person %s\n", _person_name);
}
EXPORT Person* NewPerson(void) {
return new Person;
}
EXPORT Person* NewPersonWithName(char name[]) {
return new Person(name);
}
EXPORT void DeletePerson(Person* person) {
delete person;
}
EXPORT void Person::set_name(char name[]) {
strcpy(_person_name, name);
}
EXPORT char* Person::myname(void) {
return _person_name;
}
/* File: Person.h */
#include <cstring>
class Person {
private:
char _person_name[30];
public:
Person();
~Person();
Person(char* name);
virtual void set_name(char person_name[]);
virtual char* myname();
};
// Constructor functions and function types.
extern "C" Person* NewPerson(void);
typedef Person * Person_creator(void);
extern "C" Person* NewPersonWithName(char name[]);
typedef Person * PersonWithName_creator(char name[]);
// Destructor function and function type.
extern "C" void DeletePerson(Person* person);
typedef void Person_disposer(Person*);
/* File: Client.cpp */
#include <iostream>
#include <dlfcn.h>
#include "Person.h"
class MyPerson {};
typedef void *(*Person_new)(MyPerson *);
typedef char *(*Person_myname)(MyPerson *);
typedef void (*Person_setName)(MyPerson *, char[]);
typedef void (*Person_release)(MyPerson *);
int main() {
using std::cout;
using std::cerr;
// Open the library.
void *lib_handle = dlopen("./libPerson.so", RTLD_NOW);
if (!lib_handle) {
cout << "[" << __FILE__ << "] load libPerson.so failed " << "\n";
exit(EXIT_FAILURE);
}
// Person::Person()
Person_new _person_new = (Person_new) dlsym(lib_handle, "_ZN6PersonC1Ev");
if (!_person_new) {
exit(EXIT_FAILURE);
}
// char* Person::myname(void)
Person_myname _person_myname = (Person_myname) dlsym(lib_handle, "_ZN6Person6mynameEv");
if (!_person_myname) {
exit(EXIT_FAILURE);
}
// void Person::set_name(char name[])
Person_setName _person_setName = (Person_setName) dlsym(lib_handle, "_ZN6Person8set_nameEPc");
if (!_person_setName) {
exit(EXIT_FAILURE);
}
// Person::~Person()
Person_release _person_release = (Person_release) dlsym(lib_handle, "_ZN6PersonD1Ev");
if (!_person_release) {
exit(EXIT_FAILURE);
}
MyPerson *instance = (MyPerson *) malloc(sizeof(MyPerson));
_person_new(instance);
char *_my_name = _person_myname(instance);
cout << "[" << __FILE__ << "] old name " << _my_name << "\n";
char _new_name[] = "<hello world>";
_person_setName(instance, _new_name);
_my_name = _person_myname(instance);
cout << "[" << __FILE__ << "] new name " << _my_name << "\n";
_person_release(instance);
delete instance;
cout << "[" << __FILE__ << "] end " << "\n";
// -----------------------------------------------------------------------------
// Get the NewPerson function.
Person_creator *NewPerson = (Person_creator *) dlsym(lib_handle, "NewPerson");
if (!NewPerson) {
exit(EXIT_FAILURE);
}
// Get the NewPersonWithName function.
PersonWithName_creator *NewPersonWithName = (PersonWithName_creator *) dlsym(lib_handle, "NewPersonWithName");
if (!NewPersonWithName) {
exit(EXIT_FAILURE);
}
// Get the DeletePerson function.
Person_disposer *DeletePerson =
(Person_disposer *) dlsym(lib_handle, "DeletePerson");
if (!DeletePerson) {
exit(EXIT_FAILURE);
}
// Create Person objects.
Person *person1 = NewPerson();
char person_name[] = "Cendrine";
Person *person2 = NewPersonWithName(person_name);
cout << "[" << __FILE__ << "] person1->name() = " << person1->myname() << "\n";
cout << "[" << __FILE__ << "] person2->name() = " << person2->myname() << "\n";
// Use Person objects.
char person1_name[] = "Floriane";
person1->set_name(person1_name);
cout << "[" << __FILE__ << "] person1->name() = " << person1->myname() << "\n";
char person2_name[] = "Marcelle";
person2->set_name(person2_name);
cout << "[" << __FILE__ << "] person2->name() = " << person2->myname() << "\n";
// Destroy Person objects.
DeletePerson(person1);
DeletePerson(person2);
// Close the library.
if (dlclose(lib_handle) != 0) {
exit(EXIT_FAILURE);
}
return 0;
}
# 编译动态库
g++ -shared -fvisibility=hidden -fPIC -o libPerson.so Person.cpp
# 编译 client
g++ -o client Client.cpp ./libPerson.so -ldl
// 查看符号表
// nm libPerson.so
0000000000004088 b completed.8060
U __cxa_atexit@@GLIBC_2.2.5
w __cxa_finalize@@GLIBC_2.2.5
0000000000001350 T DeletePerson
0000000000001100 t deregister_tm_clones
0000000000001170 t __do_global_dtors_aux
0000000000003db8 d __do_global_dtors_aux_fini_array_entry
0000000000004078 d __dso_handle
0000000000004080 d DW.ref.__gxx_personality_v0
0000000000003df0 d _DYNAMIC
0000000000001434 t _fini
00000000000011b0 t frame_dummy
0000000000003da8 d __frame_dummy_init_array_entry
0000000000002254 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
0000000000001419 t _GLOBAL__sub_I_Person.cpp
w __gmon_start__
0000000000002018 r __GNU_EH_FRAME_HDR
U __gxx_personality_v0@@CXXABI_1.3
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000000012ab T NewPerson
00000000000012f4 T NewPersonWithName
U printf@@GLIBC_2.2.5
0000000000001130 t register_tm_clones
U __stack_chk_fail@@GLIBC_2.4
U strcpy@@GLIBC_2.2.5
0000000000004088 d __TMC_END__
U _Unwind_Resume@@GCC_3.0
00000000000013cc t _Z41__static_initialization_and_destruction_0ii
U _ZdlPvm@@CXXABI_1.3.9
00000000000013b6 T _ZN6Person6mynameEv
0000000000001388 T _ZN6Person8set_nameEPc
000000000000122e T _ZN6PersonC1EPc
00000000000011ba T _ZN6PersonC1Ev
000000000000122e T _ZN6PersonC2EPc
00000000000011ba T _ZN6PersonC2Ev
000000000000126a T _ZN6PersonD1Ev
000000000000126a T _ZN6PersonD2Ev
U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
U _Znwm@@GLIBCXX_3.4
0000000000002000 r _ZStL19piecewise_construct
0000000000004089 b _ZStL8__ioinit
0000000000003de0 V _ZTI6Person
0000000000002010 V _ZTS6Person
0000000000003dc0 V _ZTV6Person
U _ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3
// 执行结果
./client
[Client.cpp] old name <no value>
[Client.cpp] new name <hello world>
~Person <hello world>
[Client.cpp] end
[Client.cpp] person1->name() = <no value>
[Client.cpp] person2->name() = Cendrine
[Client.cpp] person1->name() = Floriane
[Client.cpp] person2->name() = Marcelle
~Person Floriane
~Person Marcelle
c demo
/* File: Ratings.h
* Interface to libRatings.so 1.0.
*************************************/
/* Adds 'rating' to the set.
* rating: Each character adds 1 to the numeric rating
* Example: "" = 0, "*" = 1, "**" = 2, "wer " = 4.
*/
void addRating(char *rating);
/* Returns the number of ratings in the set.
*/
int ratings(void);
/* Returns the mean rating of the set.
*/
char *meanRating(void);
/* Clears the set.
*/
void clearRatings(void);
/* Ratings.h revision history
* 1. First version of this file.
*/
/* File: Ratings.c
* Compile with -fvisibility=hidden. // 1
**********************************/
#include "Ratings.h"
#include <stdio.h>
#include <string.h>
#define EXPORT __attribute__((visibility("default")))
#define MAX_NUMBERS 99
static int _number_list[MAX_NUMBERS];
static int _numbers = 0;
// Initializer.
__attribute__((constructor))
static void initializer(void) { // 2
printf("[%s] initializer()\n", __FILE__);
}
// Finalizer.
__attribute__((destructor))
static void finalizer(void) { // 3
printf("[%s] finalizer()\n", __FILE__);
}
// Used by meanRating, middleRating, frequentRating.
static char* _char_rating(int rating) {
char result[10] = "";
int int_rating = rating;
for (int i = 0; i < int_rating; i++) {
strncat(result, "*", sizeof(result) - strlen(result) - 1);
}
return strdup(result);
}
// Used by addRating.
void _add(int number) { // 4
if (_numbers < MAX_NUMBERS) {
_number_list[_numbers++] = number;
}
}
// Used by meanRating.
int _mean(void) {
int result = 0;
if (_numbers) {
int sum = 0;
int i;
for (i = 0; i < _numbers; i++) {
sum += _number_list[i];
}
result = sum / _numbers;
}
return result;
}
EXPORT
void addRating(char *rating) { // 5
if (rating != NULL) {
int numeric_rating = 0;
int pos = 0;
while (*rating++ != '\0' && pos++ < 5) {
numeric_rating++;
}
_add(numeric_rating);
}
}
EXPORT
char* meanRating(void) {
return _char_rating(_mean());
}
EXPORT
int ratings(void) {
return _numbers;
}
EXPORT
void clearRatings(void) {
_numbers = 0;
}
/* Ratings.c revision history
* 1. First version.
*/
/* Runtime.c
* Tests libRatings.so as a runtime loaded library.
***********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include "Ratings.h"
#define PASSFAIL "Passed":"Failed"
#define UNTST "Untested"
int main(int argc, char **argv) {
printf("[start_test]\n");
// Open the library.
char *lib_name = "./libRatings.so";
void *lib_handle = dlopen(lib_name, RTLD_NOW);
if (lib_handle) {
printf("[%s] dlopen(\"%s\", RTLD_NOW): Successful\n", __FILE__, lib_name);
}
else {
printf("[%s] Unable to open library: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
// Get the symbol addresses.
void (*addRating)(char*) = dlsym(lib_handle, "addRating");
if (addRating) {
printf("[%s] dlsym(lib_handle, \"addRating\"): Successful\n", __FILE__);
}
else {
printf("[%s] Unable to get symbol: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
char* (*meanRating)(void) = dlsym(lib_handle, "meanRating");
if (meanRating) {
printf("[%s] dlsym(lib_handle, \"meanRating\"): Successful\n", __FILE__);
}
else {
printf("[%s] Unable to get symbol: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
void (*clearRatings)(void) = dlsym(lib_handle, "clearRatings");
if (clearRatings) {
printf("[%s] dlsym(lib_handle, \"clearRatings\"): Successful\n", __FILE__);
}
else {
printf("[%s] Unable to get symbol: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
int (*ratings)(void) = dlsym(lib_handle, "ratings");
if (ratings) {
printf("[%s] dlsym(lib_handle, \"ratings\"): Successful\n", __FILE__);
}
else {
printf("[%s] Unable to get symbol: %s\n",
__FILE__, dlerror());
exit(EXIT_FAILURE);
}
// Setup.
addRating(NULL);
addRating("");
addRating("*");
addRating("**");
addRating("***");
addRating("*****");
addRating("*****");
// ratings.
printf("[%s] ratings(): %s\n", __FILE__, (ratings() == 6? PASSFAIL));
// meanRating.
printf("[%s] meanRating(): %s\n", __FILE__, (strcmp(meanRating(), "**") == 0)? PASSFAIL);
// clearRatings.
clearRatings();
printf("[%s] clearRatings(): %s\n", __FILE__, (ratings() == 0? PASSFAIL));
// Close the library.
if (dlclose(lib_handle) == 0) {
printf("[%s] dlclose(lib_handle): Successful\n", __FILE__);
}
else {
printf("[%s] Unable to open close: %s\n",
__FILE__, dlerror());
}
printf("[end_test]\n");
return 0;
}
/* Runtime.c revision history
* 1. First version.
*/
# File: makefile
# Image: libRatings.so 1.0
# Test applications: Dependent and Runtime.
all: dylib dependent runtime
dylib: Ratings.c Ratings.h
gcc -shared -fPIC -fvisibility=hidden -o libRatings.so Ratings.c
dependent: Dependent.c dylib
gcc -o Dependent Dependent.c ./libRatings.so
runtime: Runtime.c
gcc -o Runtime Runtime.c -ldl
clean:
rm -f libRatings.so Dependent Runtime
./Runtime
[start_test]
[Ratings.c] initializer()
[Runtime.c] dlopen("./libRatings.so", RTLD_NOW): Successful
[Runtime.c] dlsym(lib_handle, "addRating"): Successful
[Runtime.c] dlsym(lib_handle, "meanRating"): Successful
[Runtime.c] dlsym(lib_handle, "clearRatings"): Successful
[Runtime.c] dlsym(lib_handle, "ratings"): Successful
[Runtime.c] ratings(): Passed
[Runtime.c] meanRating(): Passed
[Runtime.c] clearRatings(): Passed
[Ratings.c] finalizer()
[Runtime.c] dlclose(lib_handle): Successful
[end_test]