linux 编译 c或cpp 文件为动态库 so 文件(最简单直观的模板)

简介: linux 编译 c或cpp 文件为动态库 so 文件(最简单直观的模板)

把源码编译打包为动态库so文件,做平台的可能对这些不熟悉。


对我们这些算是经常用到的。


总结个模板,一看就懂的那种,提供给有需要的人。


前提条件,机器上有 gcc工具链。


如果文件个数少,可以直接单个编译,如下:


Building shared lib...
g++ -c -fPIC  Quote.cpp -o  Quote.o
g++ -c -fPIC  QuoteExport.cpp -o  QuoteExport.o
g++ -c -fPIC  Start.cpp -o  Start.o
Generating shared lib...
g++ -shared -fPIC -o  libQuoteLib.so  ./Quote.o  ./QuoteExport.o  ./Start.o  
cp libQuoteLib.so ../


OK!


如果文件个数较多,或者夸文件夹了,层层嵌套。


那么就整个makefile模板文件,放到代码的根目录下,直接执行一个make即可。


模板文件如下:


############################################################################
#makefile,created by yangyongzhen qq:534117529
############################################################################
#****************************************************************************
# Cross complie path
#****************************************************************************
#GCC_PATH=D:\msysgit\mingw
CROSS_COMPILE=
CC     := $(CROSS_COMPILE)gcc
CXX    := $(CROSS_COMPILE)g++
AS     := $(CROSS_COMPILE)as
AR     := $(CROSS_COMPILE)ar 
LD     := $(CROSS_COMPILE)ld
RANLIB := $(CROSS_COMPILE)ranlib
OBJDUMP:= $(CROSS_COMPILE)objdump
OBJCOPY:= $(CROSS_COMPILE)objcopy
STRIP  := $(CROSS_COMPILE)strip
#****************************************************************************
# Flags
#****************************************************************************
CFLAGS= 
LDSCRIPT= 
LDFLAGS= 
#****************************************************************************
# Source files
#****************************************************************************
SRC_C=$(shell find . -name "*.cpp")
OBJ_C=$(patsubst %.cpp, %.o, $(SRC_C))
SRCS := $(SRC_C) $(SRC_C)
OBJS := $(OBJ_C) 
#****************************************************************************
# Targets of the build
#****************************************************************************
TARGET    := libQuoteLib
.PHONY: clean
all:  prebuild  $(TARGET).so
#****************************************************************************
# TARGET
#****************************************************************************
prebuild:
  @echo Building shared lib...
$(TARGET).so : $(OBJS)
  @echo Generating shared lib...
  $(CXX) -shared -fPIC -o  $(TARGET).so $(OBJS) 
  cp $(TARGET).so ../
  @echo OK!
%.o : %.cpp
  $(CXX) -c -fPIC $(CFLAGS) $< -o  $@
clean:
  @echo The following files:
  rm  -f  $(TARGET) *.so
  find . -name "*.[od]" |xargs rm
  @echo Removed!


注:在linux上,源文件的函数或方法前,不需要声明 __declspec(dllexport)


在WIn32上才需要。


所以在头文件中一般会看到:


#ifdef _WIN32
#define TAP_CDECL  __cdecl
#define TAP_DLLEXPORT __declspec(dllexport)
#else
#define TAP_CDECL
#define TAP_DLLEXPORT
#endif


__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。


被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。


_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。


C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。


带有可变参数的函数必须且只能使用_cdecl方式


__cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。


1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈。


2、__cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。


3、__fastcall调用约定:它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。


4、thiscall仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。


5、nakedcall采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。


关于__declspec的解释,转自:CSDN博主「fengbingchun」


原文链接:https://blog.csdn.net/fengbingchun/article/details/78825004


__declspec是Microsoft VC中专用的关键字,它配合着一些属性可以对标准C/C++进行扩充。__declspec关键字应该出现在声明的前面。


__declspec(dllexport)用于Windows中的动态库中,声明导出函数、类、对象等供外面调用,省略给出.def文件。即将函数、类等声明为导出函数,供其它程序调用,作为动态库的对外接口函数、类等。


.def文件(模块定义文件)是包含一个或多个描述各种DLL属性的Module语句的文本文件。.def文件或__declspec(dllexport)都是将公共符号导入到应用程序或从DLL导出函数。如果不提供__declspec(dllexport)导出DLL函数,则DLL需要提供.def文件。


__declspec(dllimport)用于Windows中,从别的动态库中声明导入函数、类、对象等供本动态库或exe文件使用。当你需要使用DLL中的函数时,往往不需要显示地导入函数,编译器可自动完成。


不使用__declspec(dllimport)也能正确编译代码,但使用__declspec(dllimport)使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于DLL中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL边界的函数调用中。声明一个导入函数,是说这个函数是从别的DLL导入。一般用于使用某个DLL的exe中。


---------------------  


相关文章
|
4天前
|
Linux 开发工具 C语言
Linux 安装 gcc 编译运行 C程序
Linux 安装 gcc 编译运行 C程序
23 0
|
15小时前
|
Linux Go 数据安全/隐私保护
Linux 中的文件属性解析
在 Linux 系统中,每个文件和目录有一组属性控制其操作和访问权限。了解这些属性对有效管理文件至关重要。文件属性包括:文件类型(如 `-` 表示普通文件,`d` 表示目录),权限(如 `rwx` 表示所有者权限,`r-x` 表示组和其他用户权限),所有者,组,硬链接数,文件大小和最后修改时间。通过 `chown` 和 `chmod` 命令可更改文件所有者、所属组及权限。此外,还有特殊权限(如 SUID、SGID)和 ACL(访问控制列表)提供更精细的访问控制。
|
1天前
|
人工智能 Linux
Linux查找大文件的方法
Linux查找大文件的方法
|
4天前
|
固态存储 Ubuntu Linux
Linux(29) 多线程快速解压缩|删除|监视大型文件
Linux(29) 多线程快速解压缩|删除|监视大型文件
11 1
|
4天前
|
Ubuntu Linux 数据安全/隐私保护
Linux(24) 如何在Ubuntu中操作rootfs.img文件
Linux(24) 如何在Ubuntu中操作rootfs.img文件
9 0
|
4天前
|
Linux 开发工具 Android开发
Docker系列(1)安装Linux系统编译Android源码
Docker系列(1)安装Linux系统编译Android源码
7 0
|
8天前
|
安全 Linux 开发工具
Linux中可引起文件时间戳改变的相关命令
【4月更文挑战第12天】Linux中可引起文件时间戳改变的相关命令
18 0
|
10天前
|
Linux Shell 开发工具
Linux文件常用操作
Linux文件常用操作(几乎覆盖所有日常使用)
84 0
|
11天前
|
Linux 内存技术 Perl
【ZYNQ】制作从 QSPI Flash 启动 Linux 的启动文件
【ZYNQ】制作从 QSPI Flash 启动 Linux 的启动文件
|
17天前
|
Linux
linux 超过4个G的文件传不上去的解决办法
linux 超过4个G的文件传不上去的解决办法
9 0