动态链接库的生成和使用(二)

1、生成动态库文件libtest.so

Demo目录下创建testso文件夹在下面创建test.cpp、test.h和Makefile文件

test.cpp:

#include <stdio.h>
#include <stdlib.h>
extern "C"
double calc_pi()
{
	double x = 0;
	double y = 0;
	double pi = 0;
	int num = 0;
	int iter = 0;
	const int try_times = 10000000;
	const double max_val = 32767.0;
	while (iter++ <= try_times)
	{
		x = (double)(rand() % 32768) / max_val;
		y = (double)(rand() % 32768) / max_val;
		if ((x * x + y * y) <= 1)
			num++;
	}
	pi = (4.0 * num) / try_times;
	return pi;
}

test.h

extern "C"
double calc_pi();

Makefile文件

EXECUTABLE:= libtest.so
LIBDIR:=
LIBS:=
INCLUDES:=.
SRCDIR:=

CC:=g++
CFLAGS:= -g -fPIC -Wall -O0 
CPPFLAGS:= $(CFLAGS)
CPPFLAGS+= $(addprefix -I,$(INCLUDES))
CPPFLAGS+= -I.
CPPFLAGS+= -MMD

RM-F:= rm -f

SRCS:= $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR)))
OBJS:= $(patsubst %.cpp,%.o,$(SRCS))
DEPS:= $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS:= $(filter-out $(wildcard $(DEPS)),$(DEPS))


.PHONY : all deps objs clean
all:$(EXECUTABLE)
deps:$(DEPS)

objs:$(OBJS)
clean:
	@$(RM-F) *.o
	@$(RM-F) *.d

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS):
	@$(RM-F) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(EXECUTABLE) : $(OBJS)
	$(CC) -shared -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))

 

这个Makefile文件定义了一个用于构建共享库(libtest.so)的构建系统。下面是对Makefile中各个部分的解释:

  1. 变量定义:

    • EXECUTABLE:定义了最终生成的动态库文件的名称,这里是libtest.so
    • LIBDIR:库文件搜索目录,这里没有指定,默认为空。
    • LIBS:链接时需要的库,这里没有指定,默认为空。
    • INCLUDES:头文件搜索目录,这里设置为当前目录(.)。
    • SRCDIR:源文件搜索目录,这里没有指定,默认为空。
    • CC:编译器,这里设置为g++
    • CFLAGS:编译器标志,包括调试信息(-g)、生成位置无关代码(-fPIC)、开启所有警告(-Wall)、优化等级为0(-O0)。
    • CPPFLAGS:预处理器标志,这里包括了CFLAGS和头文件搜索路径。
  2. 模式规则:

    • RM-F:定义了一个删除文件的命令,使用rm -f
    • SRCS:定义了所有源文件(.cpp),包括当前目录和SRCDIR目录下的源文件。
    • OBJS:定义了所有目标文件(.o),由源文件名转换而来。
    • DEPS:定义了所有依赖文件(.d),由目标文件名转换而来。
    • MISSING_DEPS:找出缺失的依赖文件。
  3. 目标规则:

    • .PHONY:声明了alldepsobjsclean为伪目标。
    • all:默认目标,依赖于$(EXECUTABLE),即构建最终的库文件。
    • deps:依赖于$(DEPS),即生成所有依赖文件。
    • objs:依赖于$(OBJS),即编译所有源文件生成目标文件。
    • clean:清理目标,删除所有生成的目标文件和依赖文件。
  4. 条件判断:

    • ifneq ($(MISSING_DEPS),):如果存在缺失的依赖文件,则对每个缺失的依赖文件执行删除对应目标文件的操作。
  5. 包含依赖:

    • -include $(DEPS):包含所有依赖文件,这样Makefile就可以根据这些文件来确定何时需要重新编译。
  6. 最终构建命令:

    • $(EXECUTABLE):构建目标,依赖于所有目标文件$(OBJS)。使用$(CC)编译器,-shared标志来生成共享库,链接时可能还会包含库目录和库文件。

Demo目录下执行make命令,可以生成libtest.so 动态库文件。

 

2、使用动态库文件libtest.so

Demo目录下创建testexe目录,在下面创建testexe.cpp和makefile文件

testexe.cpp:

#include <iostream>
#include "test.h"
using namespace std;
int main()
{
	printf("1:call calc_pi 2:exit\n");
	while(true)
	{
		int number = 0;
		cin >> number;
		switch(number)
		{
			case 1:
			{
				double pi = calc_pi();
				cout << "pi is " << pi << endl;
				break;
			}
			case 2:
				return 0;
			default:
				break;
		}
	}
	return 0;
}

makefile文件

EXECUTABLE:= testexe
LIBDIR:=../testso
LIBS:=test
INCLUDES:=../testso
SRCDIR:=

CC:=g++
CFLAGS:= -g -Wall -O0 
CPPFLAGS:= $(CFLAGS)
CPPFLAGS+= $(addprefix -I,$(INCLUDES))
CPPFLAGS+= -I.
CPPFLAGS+= -MMD

RM-F:= rm -f

SRCS:= $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR)))
OBJS:= $(patsubst %.cpp,%.o,$(SRCS))
DEPS:= $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS:= $(filter-out $(wildcard $(DEPS)),$(DEPS))


.PHONY : all deps objs clean
all:$(EXECUTABLE)
deps:$(DEPS)

objs:$(OBJS)
clean:
	@$(RM-F) *.o
	@$(RM-F) *.d

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS):
	@$(RM-F) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(EXECUTABLE) : $(OBJS)
	$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))

相比前面生成动态库的makefile,这里的

EXECUTABLE:定义了最终生成的可执行文件testexe

LIBDIR:库文件搜索目录,设置为../testso目录

LIBS:链接时需要的动态库名称,设置为test

INCLUDES:头文件搜索目录,这里设置为../testso

生成testexe文件编译命令:

$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))  

将动态库所在路径testso添加到LD_LIBRARY_PATH中

export LD_LIBRARY_PATH = ../testso:$LD_LIBRARY_PATH

 

3、调用动态库文件libtest.so

Demo目录下创建dtest目录,其中创建t.cpp文件和Makefile文件

t.cpp

#include <dlfcn.h>
#include <iostream>
using namespace std;
typedef double (*CALC_PI)();
int main()
{

	void* handle = dlopen("../testso/libtest.so",RTLD_NOW);
	if(!handle)
	{
		cout << "can't open the dll libtest.so" <<endl;
		return 0;
	}
	CALC_PI calc_pi =(CALC_PI) dlsym(handle,"calc_pi");
	if(!calc_pi)
	{
		cout << "can't get the calc_pi" <<endl;
		return 0;
	}
	double pi = calc_pi();
	cout << "pi is " << pi << endl;
	dlclose(handle);
	return 0;
}

makefile

EXECUTABLE:= test
LIBDIR:=
LIBS:=dl
INCLUDES:=
SRCDIR:=

CC:=g++
CFLAGS:= -g  -Wall -O0 
CPPFLAGS:= $(CFLAGS)
CPPFLAGS+= $(addprefix -I,$(INCLUDES))
CPPFLAGS+= -I.
CPPFLAGS+= -MMD

RM-F:= rm -f

SRCS:= $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR)))
OBJS:= $(patsubst %.cpp,%.o,$(SRCS))
DEPS:= $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS:= $(filter-out $(wildcard $(DEPS)),$(DEPS))


.PHONY : all deps objs clean
all:$(EXECUTABLE)
deps:$(DEPS)

objs:$(OBJS)
clean:
	@$(RM-F) *.o
	@$(RM-F) *.d

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS):
	@$(RM-F) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(EXECUTABLE) : $(OBJS)
	$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))

 

posted on 2024-08-31 17:55  轩邈、  阅读(60)  评论(0编辑  收藏  举报

导航