Skip to content

Instantly share code, notes, and snippets.

@mine260309
Last active July 26, 2017 11:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mine260309/add0168e1bd5066335ff to your computer and use it in GitHub Desktop.
Save mine260309/add0168e1bd5066335ff to your computer and use it in GitHub Desktop.
Sample code for dynamic libraries loadling a static library
#include "common.h"
#include <cstdio>
#include <string>
static TCommonStruct GlobalStatic(0, "GlobalStatic");
TCommonStruct* GetGlobalStatic()
{
return &GlobalStatic;
}
TCommonStruct* GetFunctionStatic()
{
static TCommonStruct FunctionStatic(1, "FunctionStatic");
return &FunctionStatic;
}
TCommonStruct GlobalNonStatic(2, "GlobalNonStatic");
TCommonStruct* GetGlobalNonStatic()
{
return &GlobalNonStatic;
}
#include <string>
class TCommonStruct
{
public:
int Mint;
std::string MString;
TCommonStruct(int i, std::string s)
: Mint(i),
MString(s)
{}
};
TCommonStruct* GetGlobalStatic();
TCommonStruct* GetFunctionStatic();
TCommonStruct* GetGlobalNonStatic();
#include "common.h"
#include <cstdio>
extern "C" {
TCommonStruct* Dynamic1GetGlobalStatic()
{
TCommonStruct* t = GetGlobalStatic();
::printf("%s: %p\n", __func__, t);
return t;
}
TCommonStruct* Dynamic1GetFunctionStatic()
{
TCommonStruct* t = GetFunctionStatic();
::printf("%s: %p\n", __func__, t);
return t;
}
TCommonStruct* Dynamic1GetGlobalNonStatic()
{
TCommonStruct* t = GetGlobalNonStatic();
::printf("%s: %p\n", __func__, t);
return t;
}
static int i = 1;
int GetInt()
{
return i;
}
}
class TCommonStruct;
extern "C" {
TCommonStruct* Dynamic1GetGlobalStatic();
TCommonStruct* Dynamic1GetFunctionStatic();
TCommonStruct* Dynamic1GetGlobalNonStatic();
int GetInt();
}
#include "common.h"
#include <cstdio>
extern "C" {
TCommonStruct* Dynamic2GetGlobalStatic()
{
TCommonStruct* t = GetGlobalStatic();
::printf("%s: %p\n", __func__, t);
return t;
}
TCommonStruct* Dynamic2GetFunctionStatic()
{
TCommonStruct* t = GetFunctionStatic();
::printf("%s: %p\n", __func__, t);
return t;
}
TCommonStruct* Dynamic2GetGlobalNonStatic()
{
TCommonStruct* t = GetGlobalNonStatic();
::printf("%s: %p\n", __func__, t);
return t;
}
static int i = 2;
int GetInt()
{
return i;
}
}
class TCommonStruct;
extern "C" {
TCommonStruct* Dynamic2GetGlobalStatic();
TCommonStruct* Dynamic2GetFunctionStatic();
TCommonStruct* Dynamic2GetGlobalNonStatic();
int GetInt();
}
This is the sample code for dynamic libraries loadling a static library, the behavior could be different with different compile/link options and dlopen() options.
#include "dynamic1.h"
#include "dynamic2.h"
#include <cstdio>
#include <cstdlib>
#include <dlfcn.h>
//#define DIRECT_CALL_SO
//#define USE_RTLD_GLOBAL
typedef TCommonStruct* (*FuncGetCommonStruct)();
typedef int (*FuncGetInt)();
#define CheckNotNull(p) \
do {\
if (p == NULL) {\
char *errstr;\
errstr = dlerror();\
if (errstr != NULL) {\
::printf("%s[%d] got NULL: %s\n", __func__, __LINE__, errstr);\
}\
else {\
::printf("%s[%d] got NULL\n", __func__, __LINE__);\
}\
::abort();\
}\
}\
while(0)
#ifndef DIRECT_CALL_SO
void TestLoadDynamic1()
{
void* handle = ::dlopen("./libdynamic1.so", RTLD_LAZY
#ifdef USE_RTLD_GLOBAL
| RTLD_GLOBAL
#endif
);
CheckNotNull(handle);
FuncGetCommonStruct func;
func = reinterpret_cast<FuncGetCommonStruct>(
::dlsym(handle, "Dynamic1GetGlobalStatic"));
CheckNotNull(func);
func();
func = reinterpret_cast<FuncGetCommonStruct>(
::dlsym(handle, "Dynamic1GetFunctionStatic"));
CheckNotNull(func);
func();
func = reinterpret_cast<FuncGetCommonStruct>(
::dlsym(handle, "Dynamic1GetGlobalNonStatic"));
CheckNotNull(func);
func();
FuncGetInt f = reinterpret_cast<FuncGetInt>(
::dlsym(handle, "GetInt"));
CheckNotNull(f);
::printf("GetInt returns %d\n", f());
}
void TestLoadDynamic2()
{
void* handle = ::dlopen("./libdynamic2.so", RTLD_LAZY
#ifdef USE_RTLD_GLOBAL
| RTLD_GLOBAL
#endif
);
CheckNotNull(handle);
FuncGetCommonStruct func;
func = reinterpret_cast<FuncGetCommonStruct>(
::dlsym(handle, "Dynamic2GetGlobalStatic"));
CheckNotNull(func);
func();
func = reinterpret_cast<FuncGetCommonStruct>(
::dlsym(handle, "Dynamic2GetFunctionStatic"));
CheckNotNull(func);
func();
func = reinterpret_cast<FuncGetCommonStruct>(
::dlsym(handle, "Dynamic2GetGlobalNonStatic"));
CheckNotNull(func);
func();
FuncGetInt f = reinterpret_cast<FuncGetInt>(
::dlsym(handle, "GetInt"));
CheckNotNull(f);
::printf("GetInt returns %d\n", f());
}
#endif
int main()
{
#ifdef DIRECT_CALL_SO
Dynamic1GetGlobalStatic();
Dynamic1GetFunctionStatic();
Dynamic1GetGlobalNonStatic();
::printf("GetInt returns %d\n", GetInt());
Dynamic2GetGlobalStatic();
Dynamic2GetFunctionStatic();
Dynamic2GetGlobalNonStatic();
::printf("GetInt returns %d\n", GetInt());
#else
TestLoadDynamic1();
TestLoadDynamic2();
#endif
return 0;
}
CXX = g++
AR = ar
RM = rm -f
CPPFLAGS = -g -Wall -Wextra
lib_target = libcommon.a
lib_srcs += common.cpp
so1_target = libdynamic1.so
so1_srcs += dynamic1.cpp
so2_target = libdynamic2.so
so2_srcs += dynamic2.cpp
main_srcs += main.cpp
srcs = $(lib_srcs) $(so1_srcs) $(so2_srcs) $(main_srcs)
so_objs = $(subst .cpp,.o,$(so1_srcs))
so_objs += $(subst .cpp,.o,$(so2_srcs))
LIB_TARGETS += $(lib_target)
SO_TARGETS += $(so1_target) $(so2_target)
.PHONY: clean run
all: main
main: $(LIB_TARGETS) $(SO_TARGETS)
g++ -o main $(main_srcs) -ldl
# g++ -DDIRECT_CALL_SO -o main $(main_srcs) -L. -ldynamic1 -ldynamic2
$(LIB_TARGETS): common.o
$(AR) rcs $@ $^
$(so1_target):
$(CXX) $(CPPFLAGS) -fPIC -shared -o $@ $(so1_srcs) -L. -lcommon
$(so2_target):
$(CXX) $(CPPFLAGS) -fPIC -shared -o $@ $(so2_srcs) -L. -lcommon
*.o:
$(CXX) $(CPPFLAGS) -o $@ $^
clean:
$(RM) main *.o $(LIB_TARGETS) $(SO_TARGETS)
run: main
LD_LIBRARY_PATH=. ./main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment