带有外部 #define 和 typedef 结构的静态库

Static Library with extern #define and typedef struct

本文关键字:结构 静态 typedef 外部 #define      更新时间:2023-10-16

我正在尝试创建一个静态库,其中库的某些方面可以在外部定义(在编译的库代码之外(。

对于函数定义,我可以在库中使用 extern void foo() declarations编译库而不会出现问题,然后在引用静态库的代码中定义foo()的内容。

我还想在静态库中制作一些#define valuestypedef structs,可在外部编辑。

如果我删除 #defines 或typedef structs declarations,那么我将无法编译库。

所有使用 extern 的尝试也会失败。

这可能吗?如果是这样,我该怎么做?

问候John。

#define是在

编译时处理的,因此您无法在(编译的(库之外编辑这些内容。

typedef s 和 struct s 定义内存布局并偏移到这些数据类型中。这些在编译时处理,以在编译的代码中插入正确的偏移量以访问成员,因此也在编译时处理,并且不能在(编译的(库之外进行编辑。

不过,您可以将库函数传递void *指向数据结构的指针,并传递库函数来处理这些外部定义的数据类型。例如:

void genericSort(void *ArrayToSort, int (*cmp)(void *, void *));

在这里,你向库函数传递一个要排序的数组和一个比较两个元素的函数,而库不知道这个数组包含什么。

对于#define值,您可以在库的头文件中将这些值声明为外部常量,类似于函数。

extern const int LIBRARY_USERS_VALUE;

这会强制应用程序代码声明常量本身,它也可以使用#define来执行此操作。

// Value used by the library, and elsewhere in this code.
#define ARBITRARY_NUMBER    69
// Define the constant declared in the library.
const int LIBRARY_USERS_VALUE = ARBITRARY_NUMBER;

正如其他地方提到的,structtypedef有点棘手。 但是,您可以将这些位分为库所需的位和应用程序使用的位。 一种常用的技术是定义库所需的标头,该标头的末尾还有一个应用程序可以填写的"泛型"标记。

// Declare a type that points to a named, but undefined
// structure that the application code must provide.
typedef struct user_struct_tag* user_struct_pointer;
// Declare a type for a library structure, that refers to
// application data using the pointer to the undefined struct.
typedef struct
{
    int userDataItemSize;
    int userDataItemCount;
    user_struct_pointer userDataPointer;
} library_type;

然后,应用程序代码必须声明结构(带有标记(本身。

// Define the structure referred to by the library in the application.
struct user_struct_tag
{
    int dataLength;
    char dataString[32];
};
// And typedef it if you need too.
typedef struct user_struct_tag user_data_type;

您可以使用许多其他类似的方法,前提是您的库不需要了解应用程序代码中的数据结构。 如果是这样,则该结构的声明需要在编译时可供库使用。 在这些情况下,您需要考虑库的实际用途,以及是否需要使用某种数据抽象来传递信息。 例如,XML,TLV等。

请参阅#define是预处理器符号,因此在编译时,它将替换为其原始值。因此,将它们extern在您的库中没有任何意义。

如果你想要某种编辑类型的访问,那么使用编译器时间定义对于gcc,您可以使用-D-U


对于 typedef 和结构定义,使用 extern,你可以告诉编译它将在其他文件中定义,但是当你在那个时候制作库时,该定义应该在那里。所以你想做什么是不可能的。