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中。


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


相关文章
|
2月前
|
存储 数据管理 Linux
区分Linux中.tar文件与.tar.gz文件的不同。
总之,".tar"文件提供了一种方便的文件整理方式,其归档但不压缩的特点适用于快速打包和解压,而".tar.gz"文件通过额外的压缩步骤,尽管处理时间更长,但可以减小文件尺寸,更适合于需要节约存储空间或进行文件传输的场景。用户在选择时应根据具体需求,考虑两种格式各自的优劣。
395 13
|
4月前
|
Linux 虚拟化 iOS开发
Rocky Linux 10 x86_64 OVF (sysin) - VMware 虚拟机模板
Rocky Linux 10 x86_64 OVF (sysin) - VMware 虚拟机模板
280 35
Rocky Linux 10 x86_64 OVF (sysin) - VMware 虚拟机模板
|
4月前
|
Linux 虚拟化 iOS开发
Rocky Linux 10 aarch64 OVF (sysin) - Apple silicon VMware 虚拟机模板
Rocky Linux 10 aarch64 OVF (sysin) - Apple silicon VMware 虚拟机模板
179 34
Rocky Linux 10 aarch64 OVF (sysin) - Apple silicon VMware 虚拟机模板
|
3月前
|
安全 Linux
Linux赋予文件000权限的恢复技巧
以上这些步骤就像是打开一扇锁住的门,步骤看似简单,但是背后却有着严格的逻辑和规则。切记,在任何时候,变更文件权限都要考虑安全性,不要无谓地放宽权限,那样可能
133 16
|
3月前
|
存储 Linux 数据处理
深入剖析Linux中一切即文件的哲学和重定向的机制
在计算机的奇妙世界中,Linux的这套哲学和机制减少了不同类型资源的处理方式,简化了抽象的概念,并蕴藏着强大的灵活性。就像变戏法一样,轻轻松松地在文件、程序与设备之间转换数据流,标准输入、输出、错误流就在指尖舞动,程序的交互和数据处理因此变得既高效又富有乐趣。
56 4
|
4月前
|
Ubuntu Linux
"unzip"命令解析:Linux下如何处理压缩文件。
总的来说,`unzip`命令是Linux系统下一款实用而方便的ZIP格式文件处理工具。本文通过简明扼要的方式,详细介绍了在各类Linux发行版上安装 `unzip`的方法,以及如何使用 `unzip`命令进行解压、查看和测试ZIP文件。希望本文章能为用户带来实际帮助,提高日常操作的效率。
606 12
|
3月前
|
Linux
linux文件重命名命令
本指南介绍Linux文件重命名方法,包括单文件操作的`mv`命令和批量处理的`rename`命令。`mv`可简单更改文件名并保留扩展名,如`mv old_file.txt new_name.txt`;`rename`支持正则表达式,适用于复杂批量操作,如`rename &#39;s/2023/2024/&#39; *.log`。提供实用技巧如大小写转换、数字序列处理等,并提醒覆盖风险与版本差异,建议使用`-n`参数预览效果。
|
3月前
|
Linux 编译器 vr&ar
Linux的动态库与静态库
静态库在编译时直接嵌入到最终的可执行文件中。
91 0
|
Linux
百度搜索:蓝易云【Linux中如何对文件进行压缩和解压缩?】
这些是在Linux中进行文件压缩和解压缩的常见方法。根据您的需求和具体情况,可能会使用其他压缩工具和选项。您可以通过查阅相应命令的帮助文档来获取更多详细信息。
165 1
|
NoSQL Java Linux
Linux常用命令(文件目录操作、拷贝移动、打包压缩、文本编辑、查找)
Linux常用命令(文件目录操作、拷贝移动、打包压缩、文本编辑、查找)