C 언어--정적 라이브러리 및 동적 라이브러리

첨가되는: GitHub 업로드 코드.

검증결론

서로 다른 동적 라이브러리에 있는 동일한 이름의 함수를 포함하는 Windows와 Linux 간에는 충돌이 없습니다.

예비 지식

정적 라이브러리와 동적 라이브러리는 본질적으로 프로그램입니다. 일반적으로 프로젝트에서 라이브러리를 사용하는 두 가지 목적이 있습니다. 하나는 프로젝트에서 너무 많은 소스 파일을 유지하지 않고 프로그램을 더 간결하게 만드는 것이고, 다른 하나는 소스 코드를 기밀로 유지하는 것입니다. 자신의 프로그램은 오픈 소스입니다.

라이브러리파일(동적라이브러리, 정적라이브러리)을 받았을 때 사용하려면 이 라이브러리에서 제공하는 API 함수 선언, 즉 헤더파일이 있어야 프로젝트에 추가하고, 행복하게 코드를 작성할 수 있습니다.

정적 라이브러리

(1) 컴파일 시 정적 라이브러리의 해당 코드를 실행 파일에 복사하고, 실행 시 라이브러리를 링크할 필요가 없음

(2) 프로그램 실행시 라이브러리를 로드할 필요가 없고 실행속도가 빠름(장점)

(3) 더 많은 디스크와 메모리 공간을 차지하며 정적 라이브러리를 업그레이드한 후 프로그램을 다시 컴파일해야 하며 라이브러리 업그레이드가 불편합니다(단점
) .均以.lib开头。Windows下静态库以.lib 结尾。Linux下以.a结尾。

Windows 정적 라이브러리 생성 방법:

VS를 사용하여 생성할 때 빈 프로젝트 선택 시 정적 라이브러리 또는 동적 라이브러리를 직접 선택하거나 생성 후 수정할 수 있습니다.

Linux 정적 라이브러리 생성 방법:

生成静态库,需要先对源文件进行汇编操作 (使用参数 -c) 得到二进制格式的目标文件 (.o 格式), 然后在通过 ar 工具将目标文件打包就可以得到静态库文件了 (libxxx.a)。

ar 도구를 사용하여 정적 라이브러리를 만들 때 세 가지 매개변수가 필요합니다.

参数c:创建一个库,不管库是否存在,都将创建。
参数s:创建目标文件索引,这在创建较大的库时能加快时间。
参数r:在库中插入模块 (替换)。默认新的成员添加在库的结尾处,如果模块名已经在库中存在,则替换同名的模块。

1단계:

시스템 프롬프트에 다음 명령을 입력하여 hello.o 파일을 가져옵니다.

gcc -c hello.c

Linux에서 정적 라이브러리 파일 이름의 명명 규칙에는 lib 접두사가 붙고 그 뒤에 정적 라이브러리 이름이 오고 확장자는 .a입니다. 예를 들어 만들 정적 라이브러리의 이름은 hello이고 정적 라이브러리의 파일 이름은 libhello.a입니다.

2단계:

이제 .o 파일이 있으므로 패키징하겠습니다. ar 명령으로 정적 라이브러리를 만듭니다. 시스템 프롬프트에서 다음 명령을 입력하면 정적 라이브러리 파일 libhello.a가 생성됩니다.

ar -rcs libmyhello.a hello.o //可接多个.o文件

3. 생성된 정적 라이브러리 libmyhello.a 및 해당 헤더 파일 head.h를 사용자에게 릴리스합니다.

정적 라이브러리 사용:

정적 라이브러리를 연결, 컴파일 및 실행하고 컴파일할 때 정적 라이브러리의 경로와 이름을 지정합니다.

-L: 指定库所在的目录 (相对或者绝对路径)
-l: 指定库的名字,需要掐头 (lib) 去尾 (.a) 剩下的才是需要的静态库的名字
gcc -o hello main.c -L. -l myhello
./hello

-o는 출력 파일의 이름을 지정하라는 의미로 지정하지 않으면 .c 파일에 따라 기본 이름이 생성되며 여기서는 hello를 지정한다.
-main.c는 정적 라이브러리를 사용할 프로그램 파일을 나타냅니다.
-L은 타사 라이브러리 디렉토리를 지정하며 여기서 -L.은 현재 디렉토리에서 타사 라이브러리를 찾는 것을 의미합니다.
-l myhello(-l 사이에 공백을 포함하거나 포함하지 않고 머리를 꼬집고 꼬리를 제거)는 libhello.a 또는 libhello.so라는 이름의 라이브러리를 연결하는 것을 의미합니다.

동적 라이브러리

(1) 컴파일 시점에 공유 라이브러리(동적 라이브러리)가 사용된 심볼(함수)만 기록하고 공유 라이브러리에 해당 코드를 복사하지 않고 런타임에 공유 라이브러리를 로드합니다.
(2) 프로그램이 라이브러리에 코드를 포함하지 않고 코드 크기가 작습니다(장점).
(3) 재컴파일 없이 라이브러리 업그레이드가 용이하다(장점).
(4) 더 넓은
접미사 사용 : 均以.lib开头。在win系统下后缀为.dll,在Linux下后缀为.so。Windows에서 사용하는 제작 도구가 다르기 때문에 획득한 라이브러리 파일이 다릅니다.참고: 동적 라이브러리에는 실행 권한이 있지만 정적 라이브러리에는 없습니다.

Windows 동적 라이브러리 생성 방법: VS를 사용하여 생성할 때 정적 라이브러리 또는 빈 프로젝트 선택 시 동적 라이브러리를 직접 선택하거나 생성 후 수정할 수 있습니다.

Linux 동적 라이브러리 생성 방법**:

生成动态链接库是直接使用 gcc 命令并且需要添加 -fPIC(-fpic) 以及 -shared 参数。

-fPIC 或 -fpic 参数的作用是使得 gcc 生成的代码是与位置无关的,也就是使用相对位置。
-shared参数的作用是告诉编译器生成一个动态链接库(无位置要求)。

1단계:

정적 및 동적 라이브러리는 모두 .o 파일로 생성됩니다. 따라서 먼저 정적 라이브러리의 .c 파일을 gcc를 통해 .o 파일로 컴파일해야 하고 시스템 프롬프트에서 다음 명령을 입력하여 hello.o 파일을 얻는다.

gcc -c hello.c -fpic

2단계:

Linux에서 동적 라이브러리 파일 이름의 명명 규칙은 lib 접두사가 붙고 뒤에 정적 라이브러리 이름이 오고 확장자는 .so입니다. 예를 들어 만들 정적 라이브러리의 이름은 hello이고 동적 라이브러리의 파일 이름은 libhello.so입니다.

-shared 매개변수를 사용하여 동적 라이브러리를 생성합니다. 시스템 프롬프트에서 다음 명령을 입력하여 동적 라이브러리 파일 libhello.so를 생성합니다.

gcc -shared -o libhello.so hello.o,

위의 두 단계는 서로 연결될 수 있습니다.

gcc -shared -fPIC -o libhello.so hello.c

동적 라이브러리 사용:

실행 가능한 프로그램을 생성합니다.

gcc -o main main.c -L . -lhello
./main

동적 라이브러리를 사용하는 프로그램을 실행할 때 동적 라이브러리를 로드할 수 없다는 메시지가 표시될 수 있습니다.

Linux提供了一个动态链接器:
동적링커는 응용프로그램과 독립된 프로세스로 운영체제에 속해 있어 사용자의 프로그램이 동적라이브러리를 불러올 필요가 있을 때 동적링커가 작동하기 시작한다. gcc를 통해 -L 매개변수로 지정된 경로.

그렇다면 동적 링커는 특정 동적 라이브러리를 어떻게 검색합니까?내부에는 높은 우선 순위에서 낮은 우선 순위의 기본 검색 순서가 있습니다.

1.可执行文件内部的 DT_RPATH 段
2.系统的环境变量 LD_LIBRARY_PATH //相当于操作系统提供的全局变量,里面可以存储一些路径。相当于PATH
3.系统动态库的缓存文件 /etc/ld.so.cache
4.存储动态库 / 静态库的系统目录 /lib/, /usr/lib 等
按照以上四个顺序,依次搜索,找到之后结束遍历,最终还是没找到,动态连接器就会提示动态库找不到的错误信息。

솔루션(위의 2, 3, 4에 해당):

环境变量동적 라이브러리의 경로를 해당 또는 에 넣기만 하면 됩니다 系统配置文件. 동적 라이브러리를 넣을 수도 있습니다 拷贝到系统库目录(또는 동적 라이브러리의 소프트 링크 파일을 이러한 시스템 라이브러리 디렉토리에 넣을 수도 있습니다).

해결 방법 1: 환경 변수 LD_LIBRARY_PATH에 라이브러리 경로 추가

환경 변수 값 보기:

echo $LD_LIBRARY_PATH // 此处$是为了取到LD_LIBRARY_PATH的值,不加的话会打印出个LD_LIBRARY_PATH

여기에 이미지 설명 삽입

해결 방법 2: /etc/ld.so.cache 파일 업데이트

여기에 이미지 설명 삽입

해결 방법 3: 동적 라이브러리 파일을 시스템 라이브러리 디렉토리 /lib/ 또는 /usr/lib에 복사(또는 라이브러리의 소프트 링크 파일 넣기)

여기에 이미지 설명 삽입
동적 라이브러리의 내용이 수정되더라도 다시 복사할 필요가 없도록 소프트 링크를 사용하는 것이 좋습니다.

실행 프로그램을 시작하기 전에 또는 동적 라이브러리 경로를 설정한 후에 命令检测程序能不能够通过动态链接器加载到对应的动态库ldd라는 명령을 전달할 수 있습니다.

ldd main(可执行的程序名称)

두 개의 서로 다른 동적 라이브러리에 이름이 같은 함수가 포함되어 있는지 확인합니다.

1단계:

두 개의 동적 라이브러리 생성(새 프로젝트를 생성할 때 동적 라이브러리 옵션을 선택하거나 프로젝트 속성에서 수정하십시오. 비디오 자습서: B 스테이션 자습서를 참조하십시오) : DLL_1, DLL_2, 두 개의 동적 라이브러리에는 get_info() 함수가 포함되어 있습니다. 같은 이름. 콘텐츠는 동적 링크 라이브러리 DLL_1을 예로 사용하고 동적 링크 라이브러리 2의 해당 수정 기능은 콘텐츠를 "This is the dynamic library 2..."로 인쇄합니다. dll1.h의 콘텐츠는 다음과 같습니다
.

#pragma once
#include <stdio.h>

#ifdef WIN32
#define DllExport    __declspec( dllexport )
#else
#define DllExport    __attribute__((visibility("default")))
#endif

DllExport
void
get_info();

dll1.c의 내용은 다음과 같습니다.

#include "dll1.h"

DllExport
void
get_info()
{
	printf("这是动态库1:dll_1\n");
}

2단계:

이제 두 개의 동적 라이브러리가 있으므로 다음 단계는 기본 프로젝트 DllTest를 작성하여 두 개의 동적 라이브러리의 콘텐츠를 호출하는 것입니다.
알아채다:안에. DLL_11 및 DLL_22는 두 개의 정적 라이브러리입니다. 전체 코드 및 테스트 결과를 확인하세요.github:
DllTest.h의 내용:
여기에 이미지 설명 삽입
DllTest.c의 내용:
TEST4:
여기에 이미지 설명 삽입
TEST3:
여기에 이미지 설명 삽입
TEST2:
여기에 이미지 설명 삽입
TEST1:
여기에 이미지 설명 삽입

추천

출처blog.csdn.net/qq_39030233/article/details/128606718