c++ 写一个c静态链接库 供c或c++项目调用

c++ 写一个c静态链接库 供c或c++项目调用

静态链接库:输出的库文件及头文件提供给调用方之后,会随着编译将代码拷贝到调用者处;优点是无依赖;缺点是,静态库有更新后,所有可执行文件需要重新链接。

动态链接库:优点:编译时不需要拷贝代码,运行时动态链接,这样比较节省资源。缺点:运行时动态加载,可能影响程序执行性能。

本节通过CLion编辑器,创建c静态链接库;后通过分别给c和c++控制台项目,以达到了解静态链接库的创建和使用的基本流程。

创建c静态链接库项目

# 头文件 library.h

#ifndef CSTATICLIB_LIBRARY_H

#define CSTATICLIB_LIBRARY_H

typedef void (*callback)(void);

void add_handler(callback event);

void raise_event();

#endif // CSTATICLIB_LIBRARY_H

# library.c文件

#include "library.h"

#include

callback close;

void add_handler(callback event) {

close = event;

}

void raise_event() {

if (close != NULL) {

close();

}

}

CMakeLists.txt文件配置

cmake_minimum_required(VERSION 4.0)

project(cstaticlib C)

set(CMAKE_C_STANDARD 11)

add_library(cstaticlib STATIC library.c)

编译项目得到静态库文件

创建c可执行控制台项目

创建可执行c控制台项目,用来测试如何使用静态链接库。

引入库文件和静态库文件

创建include目录和lib目录,将静态库文件libcstaticlib.a文件拷贝到lib目录,将library.h文件拷贝到include目录下。

配置CMakeLists.txt 配置文件查找路径 链接库文件

直接在main.c文件中引入library.h头文件是会报错的,因为静态库需要将静态库文件在链接阶段和本可执行项目合并,所以需要在CMake配置文件中指定要链接哪些库;

cmake_minimum_required(VERSION 4.0)

project(testcdemo C)

set(CMAKE_C_STANDARD 11)

#设置链接库查找路径

link_directories(${PROJECT_SOURCE_DIR}/lib)

#设置头文件查找路径

include_directories(${PROJECT_SOURCE_DIR}/include)

add_executable(testcdemo main.c)

#指定要链接哪个库

#target_link_libraries(${PROJECT_NAME} libcstaticlib.a)

#库文件一般都是libxxx.a或者libxxx.lib这种格式,所以可以将文件后缀和lib前缀省略。这样写跨平台性好。

target_link_libraries(${PROJECT_NAME} cstaticlib)

编译并运行项目

在main函数中写入下面代码,编译并调试代码运行情况:

#include

#include

void onclose();

int main(void) {

callback event = onclose;

add_handler(event);

raise_event();

return 0;

}

void onclose() {

printf("Closing...\n");

}

输出

Closing...

以上便是,c可执行项目中调用静态链接库项目。

创建c++可执行控制台项目

引入库文件和头文件、配置CMakeLists.txt、编写代码步骤同上面操作;但编译报错:

FAILED: teststaticlib

: && /usr/bin/c++ -g -arch arm64 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/teststaticlib.dir/main.cpp.o -o teststaticlib -L/Users/a77/Code/teststaticlib/lib -Wl,-rpath,/Users/a77/Code/teststaticlib/lib -lcstaticlib && :

Undefined symbols for architecture arm64:

"add_handler(void (*)())", referenced from:

_main in main.cpp.o

(found _add_handler in /Users/a77/Code/teststaticlib/lib/libcstaticlib.a(library.c.o), declaration possibly missing extern "C")

"raise_event()", referenced from:

_main in main.cpp.o

ld: symbol(s) not found for architecture arm64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

add_handler函数被发现变成了_add_handler,这个属于c++为照顾c语言不支持函数重载所设计的名称管理机制,为的是函数名不重复;

windows平台可以使用VisualStudio提供的dumpbin.exe /EXPORTS xxx.dll 查看函数导出符号;macos可以使用 nm xxx.dylib 或者 otool -tV xxx.dylib 来查看

a77@iMac Code % nm /Users/a77/Code/dynamiclib/cmake-build-debug/libdynamiclib.dylib

0000000000003f50 T _add_handler

0000000000004000 S _close

0000000000003f70 T _raise_event

a77@iMac Code % otool -tV /Users/a77/Code/dynamiclib/cmake-build-debug/libdynamiclib.dylib

/Users/a77/Code/dynamiclib/cmake-build-debug/libdynamiclib.dylib:

(__TEXT,__text) section

_add_handler:

0000000000003f50 sub sp, sp, #0x10

0000000000003f54 str x0, [sp, #0x8]

0000000000003f58 ldr x8, [sp, #0x8]

0000000000003f5c adrp x9, 1 ; 0x4000

0000000000003f60 add x9, x9, #0x0

0000000000003f64 str x8, [x9]

0000000000003f68 add sp, sp, #0x10

0000000000003f6c ret

_raise_event:

0000000000003f70 stp x29, x30, [sp, #-0x10]!

0000000000003f74 mov x29, sp

0000000000003f78 adrp x8, 1 ; 0x4000

0000000000003f7c add x8, x8, #0x0

0000000000003f80 ldr x8, [x8]

0000000000003f84 subs x8, x8, #0x0

0000000000003f88 cset w8, eq

0000000000003f8c tbnz w8, #0x0, 0x3fa8

0000000000003f90 b 0x3f94

0000000000003f94 adrp x8, 1 ; 0x4000

0000000000003f98 add x8, x8, #0x0

0000000000003f9c ldr x8, [x8]

0000000000003fa0 blr x8

0000000000003fa4 b 0x3fa8

0000000000003fa8 ldp x29, x30, [sp], #0x10

0000000000003fac ret

a77@iMac Code %

从上面的输出信息可以看到 函数名确实如报错信息中所述,前面加了下划线;好在,编译器提示我们要使用 extern "C"这样的代码块解决问题:

代码如下:

#include

#include

extern "C" {

#include

}

void action();

int main() {

callback func = action;

add_handler(func);

raise_event();

return 0;

}

void action() {

std::cout << "receive event" << std::endl;

}

好了,以上便是从创建静态库项目和分别使用c和c++控制台项目引用静态库的全过程记录。

相关推荐

龟牌樱桃爽洗车水蜡好吗
bt365网站

龟牌樱桃爽洗车水蜡好吗

📅 12-10 👁️ 8138
搭建加油网络,“一桶加油”想做面向物流行业的能源供应链
标准差计算公式及解释
best365官网体育投注

标准差计算公式及解释

📅 08-02 👁️ 3034
猩猩助手安卓模拟器 软件特性
mobile365体育

猩猩助手安卓模拟器 软件特性

📅 01-01 👁️ 1643
房间小床怎么摆放?摆放原则有哪些?
bt365网站

房间小床怎么摆放?摆放原则有哪些?

📅 10-31 👁️ 8470
䔮的笔画顺序 䔮的笔画顺序是什么
mobile365体育

䔮的笔画顺序 䔮的笔画顺序是什么

📅 08-24 👁️ 1753