如何为多个C库创建常见的错误处理机制?

发布于 2025-02-12 19:15:22 字数 1165 浏览 0 评论 0原文

我的库(liba)的每个源文件都包括一个in_err.h文件。
该文件为每个可能的错误定义了枚举,以及描述相应错误的字符串数组。
有一个函数get_err_mess(),该函数返回与错误枚举相对应的错误消息。

in_err.h

typedef enum {
    E_ERR_NOERROR = OK, //OK=0
    E_ERR_1 = E_ERR_BADPARAM,
    ...
    E_ERR_MAX
} ERROR;

const char *error_description[] = {
         "No error.",
         "Bad parameter.",
         ...
         "Max error enum reached.",
};

const char * get_err_mess(ERROR err){
    ...
    return err_mess;
}

我库(liba)的每个功能都返回错误类型。

liba.a

#include "in_err.h"
ERROR func1()
{
    ERROR err = OK;
    ...
    return err
}

主程序调用liba的函数,并显示错误消息(如果有)。

main.c

#include "in_err.h"
#include "headerfromlibA.h"
int main()
{
    ERROR err = OK;

    err = func1()
    if (!err){
        err = func2()
    }

    if(err){
        printf("Error: %s\n", get_err_mess(err));
    }
    return err;
}

现在我想用相同的错误管理制作另一个库(libb),但具有自己的错误类型。
我的问题是我将有两个get_err_mess()功能具有相同的错误ID。
我想拥有一个get_err_mess()来管理liba和libb的错误。
您会推荐什么?

我看到的唯一解决方案是为每个库设置一系列错误...但是我不喜欢

Each source file of my library (libA) includes an in_err.h file.
This file defines an enum for every possible error, and an array of string describing the corresponding error.
There is a function get_err_mess() which returns the error message corresponding to the error enum.

in_err.h

typedef enum {
    E_ERR_NOERROR = OK, //OK=0
    E_ERR_1 = E_ERR_BADPARAM,
    ...
    E_ERR_MAX
} ERROR;

const char *error_description[] = {
         "No error.",
         "Bad parameter.",
         ...
         "Max error enum reached.",
};

const char * get_err_mess(ERROR err){
    ...
    return err_mess;
}

Every functions of my library (libA) returns an ERROR type.

libA.a

#include "in_err.h"
ERROR func1()
{
    ERROR err = OK;
    ...
    return err
}

The main program calls functions from libA and displays error message if any.

main.c

#include "in_err.h"
#include "headerfromlibA.h"
int main()
{
    ERROR err = OK;

    err = func1()
    if (!err){
        err = func2()
    }

    if(err){
        printf("Error: %s\n", get_err_mess(err));
    }
    return err;
}

Now I want to make another library (libB) with the same kind of error management but with its own types of errors.
My problem is that I would have two get_err_mess() functions with potentially the same error id.
I'd like to have a single get_err_mess() to manage errors from libA and libB.
What would you recommend ?

The only solution I see is to set a range of error for each library... but I don't like it

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

余生再见 2025-02-19 19:15:22

基本思想:返回堆栈上的16字节结构(uniform_error)。

err.h

#pragma once

typedef const char *(*err_msg_func)(int err);
typedef struct {
    err_msg_func err_to_msg;
    const char *name;
} ERR_SRC;

typedef struct {
    int code;
    const ERR_SRC* src;
} UNIFORM_ERROR;

static inline const char *err_msg(UNIFORM_ERROR err) {
    return err.src->err_to_msg(err.code);
}

liba.h

#pragma once

#include "err.h"

typedef enum {
    EA_ERR_NOERROR = 0,
    EA_ERR_BADPARAM,
    EA_ERR_PERMISSION,
    EA_ERR_MAX
} A_ERROR;

UNIFORM_ERROR a_func();

liba.c

#include "liba.h"

static const char *error_msg[] = {
    "No error",
    "Bad parameter",
    "No permission",
    "Max error enum reached"
};

static const char *a_error_msg(int code) {
    return error_msg[code];
}

static const ERR_SRC a_err_src = {
    a_error_msg,
    "a"
};

static UNIFORM_ERROR mkerr(A_ERROR code) {
    UNIFORM_ERROR err = {code, &a_err_src};
    return err;
}

UNIFORM_ERROR a_func()
{
    return mkerr(EA_ERR_BADPARAM);
}

libb.h

#pragma once

#include "err.h"

typedef enum {
    EB_ERR_NOERROR = 0,
    EB_ERR_NOTFOUND,
    EB_ERR_MAX
} B_ERROR;

UNIFORM_ERROR b_func();

libb.c.c

#include "libb.h"

static const char *error_msg[] = {
    "No error",
    "Not found",
    "Max error enum reached"
};

const char *b_error_msg(int code) {
    return error_msg[code];
}

static const ERR_SRC b_err_src = {
    b_error_msg,
    "b"
};

static UNIFORM_ERROR mkerr(B_ERROR code) {
    UNIFORM_ERROR err = {code, &b_err_src};
    return err;
}

UNIFORM_ERROR b_func()
{
    return mkerr(EB_ERR_NOTFOUND);
}

main.c

#include <stdio.h>
#include "liba.h"
#include "libb.h"
#include "err.h"

int main()
{
    UNIFORM_ERROR err;
    err = a_func();
    printf("Error %d from %s: %s\n", err.code, err.src->name, err_msg(err));
    err = b_func();
    printf("Error %d from %s: %s\n", err.code, err.src->name, err_msg(err));
}

输出:

Error 1 from a: Bad parameter
Error 1 from b: Not found

Basic idea: return a 16-byte struct (UNIFORM_ERROR below) on the stack.

err.h:

#pragma once

typedef const char *(*err_msg_func)(int err);
typedef struct {
    err_msg_func err_to_msg;
    const char *name;
} ERR_SRC;

typedef struct {
    int code;
    const ERR_SRC* src;
} UNIFORM_ERROR;

static inline const char *err_msg(UNIFORM_ERROR err) {
    return err.src->err_to_msg(err.code);
}

liba.h:

#pragma once

#include "err.h"

typedef enum {
    EA_ERR_NOERROR = 0,
    EA_ERR_BADPARAM,
    EA_ERR_PERMISSION,
    EA_ERR_MAX
} A_ERROR;

UNIFORM_ERROR a_func();

liba.c:

#include "liba.h"

static const char *error_msg[] = {
    "No error",
    "Bad parameter",
    "No permission",
    "Max error enum reached"
};

static const char *a_error_msg(int code) {
    return error_msg[code];
}

static const ERR_SRC a_err_src = {
    a_error_msg,
    "a"
};

static UNIFORM_ERROR mkerr(A_ERROR code) {
    UNIFORM_ERROR err = {code, &a_err_src};
    return err;
}

UNIFORM_ERROR a_func()
{
    return mkerr(EA_ERR_BADPARAM);
}

libb.h:

#pragma once

#include "err.h"

typedef enum {
    EB_ERR_NOERROR = 0,
    EB_ERR_NOTFOUND,
    EB_ERR_MAX
} B_ERROR;

UNIFORM_ERROR b_func();

libb.c:

#include "libb.h"

static const char *error_msg[] = {
    "No error",
    "Not found",
    "Max error enum reached"
};

const char *b_error_msg(int code) {
    return error_msg[code];
}

static const ERR_SRC b_err_src = {
    b_error_msg,
    "b"
};

static UNIFORM_ERROR mkerr(B_ERROR code) {
    UNIFORM_ERROR err = {code, &b_err_src};
    return err;
}

UNIFORM_ERROR b_func()
{
    return mkerr(EB_ERR_NOTFOUND);
}

main.c:

#include <stdio.h>
#include "liba.h"
#include "libb.h"
#include "err.h"

int main()
{
    UNIFORM_ERROR err;
    err = a_func();
    printf("Error %d from %s: %s\n", err.code, err.src->name, err_msg(err));
    err = b_func();
    printf("Error %d from %s: %s\n", err.code, err.src->name, err_msg(err));
}

output:

Error 1 from a: Bad parameter
Error 1 from b: Not found
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文