C语言从入门到精通-C静态库的生成及使用

发布于:2024-04-29 ⋅ 阅读:(21) ⋅ 点赞:(0)

静态库

什么是静态库

C静态库(Static Library)是C语言编程中常用的一种库文件形式。与动态库(Dynamic Library)相比,静态库在程序编译时会被完全嵌入到最终的可执行文件中,因此生成的可执行文件不依赖于外部的库文件。这意味着,无论目标系统上是否安装了相应的库,只要编译时包含了静态库,程序就可以正常运行。C静态库(Static Library)是C语言编程中常用的一种库文件形式。与动态库(Dynamic Library)相比,静态库在程序编译时会被完全嵌入到最终的可执行文件中,因此生成的可执行文件不依赖于外部的库文件。这意味着,无论目标系统上是否安装了相应的库,只要编译时包含了静态库,程序就可以正常运行。

CLion生成静态库

使用CLion生成静态库文件。

创建C语言库项目

image-20240429153738838

修改库文件.h名称

image-20240429155312623

编写库中的头文件

#ifndef FFYC_FFYC_H
#define FFYC_FFYC_H


#include <stdio.h>
#include <stdlib.h>
#include<sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>


/**
 * 启动服务器
 * @return
 */
int start_server(int port);
/**
 * 连接服务器
 * @param server_socket
 * @return 返回连接状态
 */
int conn_server(int server_socket);
/**
 * 获取前端返回的数据
 * @param conn_socket 连接状态
 * @param req_buffer 数组存储请求的字符串
 */
void receive_data(int conn_socket, char* req_buffer,int req_buffer_len);
/**
 * 打印字符串数组信息
 * @param array 字符数组
 * @param len 字符数组长度
 */
void print_array(char *array, int len);
/**
 * 获取请求数据
 * @param array
 * @param len
 * @return
 */
char* get_req_data(char *array, int len);
/**
 * 将十六进制转换为十进制
 * @param c 要转换的字符
 * @return 返回十进制数
 */
int hex2dec(char c);
/**
 * 将输入的字符串中的中文翻译为中文正确格式
 * @param url
 */
void url_decode(char url[]);
/**
 * 发送数据到web前端
 * @param conn_socket 连接的socket
 * @param data  传输的数据
 */
void send_data(int conn_socket,char* data);



#endif //FFYC_FFYC_H

编写.c文件

#include "ffyc.h"

char resp_header[] = "HTTP/1.0 200 OK\r\n"
                     "Server: my-AI-X v1.0\r\n"
                     "Content-Type: text/html;charset=utf-8\r\n"
                     "\r\n"
                     "<!DOCTYPE html><html lang='en'><head><meta charset='UTF-8'>"
                     "<title>my ai</title><link rel='shortcut icon' href='data:image/ico;base64,aWNv'/></head></html>";


int start_server(int port) {

    int yes = 1;
    int server_socket =
            socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (server_socket < 0) {

        fprintf(stderr, "[服务器] socket创建失败...\n");
        exit(EXIT_FAILURE);
    }
    printf("[服务器] 创建socket成功^_^\n");

    // 设置 SO_REUSEADDR 选项
    if (setsockopt(server_socket, SOL_SOCKET,
                   SO_REUSEADDR,
                   &yes,
                   sizeof(int)) == -1) {

        fprintf(stderr, "[服务器] 设置socket参数失败...\n");
        exit(1);
    }

    struct sockaddr_in my_sockaddr;
    my_sockaddr.sin_port = htons(port);
    my_sockaddr.sin_family = AF_INET;
    my_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    int bind_ret = bind(server_socket,
                        (struct sockaddr *) &my_sockaddr,
                        sizeof(my_sockaddr));

    if (bind_ret < 0) {
        fprintf(stderr, "[服务器] 绑定端口[%d]失败...\n", port);
        exit(EXIT_FAILURE);
    }
    printf("[服务器] 绑定端口[%d]成功....\n", port);

    int listen_ret = listen(server_socket, 200);

    if (listen_ret < 0) {
        fprintf(stderr, "[服务器] 监听端口[%d]失败...\n", port);
        exit(EXIT_FAILURE);
    }
    printf("[服务器] 监听端口[%d]成功....\n", port);

    return server_socket;

}

int conn_server(int server_socket) {
    //连接服务
    int conn_socket = accept(server_socket, NULL, NULL);

    if (conn_socket < 0) {
        fprintf(stderr, "[服务器] 连接失败....\n");
        exit(EXIT_FAILURE);
    }
    return conn_socket;
}

void receive_data(int conn_socket, char *req_buffer, int req_buffer_len) {
    ssize_t rev_ret = recv(conn_socket, req_buffer, req_buffer_len, 0);

    if (rev_ret < 0) {
        fprintf(stderr, "[服务器] 获取数据失败...\n");
        exit(EXIT_FAILURE);
    }
    if (rev_ret == 0) {
        fprintf(stderr, "[服务器] 超时或对终端主动关闭...\n");
        exit(EXIT_FAILURE);
    }
}

void print_array(char *array, int len) {
    for (int i = 0; i < len; i++) {
        if (array[i] == '\r') {
            continue;
        }
        if (array[i] == 0) break;
        printf("%c", array[i]);
    }
}

char *get_req_data(char *array) {

    unsigned long pos = strcspn(array, "\r\n");
    array[pos] = '\0';
    url_decode(array);
    return array;
}

int hex2dec(char c) {
    if ('0' <= c && c <= '9') {
        return c - '0';
    } else if ('a' <= c && c <= 'f') {
        return c - 'a' + 10;
    } else if ('A' <= c && c <= 'F') {
        return c - 'A' + 10;
    } else {
        return -1;
    }
}


void url_decode(char* url) {

    size_t len = strlen(url);
    int res_len = 0;
    char res[100];

    for (int i = 0; i < len; ++i) {
        char c = url[i];
        if (c != '%') {
            res[res_len++] = c;
        } else {
            char c1 = url[++i];
            char c0 = url[++i];
            int num = hex2dec(c1) * 16 + hex2dec(c0);
            res[res_len++] = (char)num;
        }
    }
    res[res_len] = '\0';
    strcpy(url, res);
}

void send_data(int conn_socket, char *data) {
    send(conn_socket, resp_header, strlen(resp_header), 0);
    send(conn_socket, data, strlen(data), 0);
}

生成静态库

image-20240429164751666

生成静态库文件: libffyc.a

image-20240429165016618

移植库文件到Cygwin64

拷贝xxx.a文件到Cygwin64/lib中

image-20240429165759269

image-20240429170011066

拷贝头文件xxx.h到Cygwin64/usr/include

image-20240429170411336

image-20240429170522197

CLion中应用静态库

cmake_minimum_required(VERSION 3.28)
project(lib_hello C)

set(CMAKE_C_STANDARD 99)

add_executable(lib_hello main.c)

target_link_libraries(${PROJECT_NAME} libffyc.a)

image-20240429171436179

测试使用

#include <stdio.h>
#include "ffyc.h"
int main(void) {

    start_server(9999);
    return 0;
}