【问题标题】:Hide struct definition in static library在静态库中隐藏结构定义
【发布时间】:2010-05-24 07:10:03
【问题描述】:

我需要向客户端提供一个 C 静态库,并且需要能够使结构定义不可用。最重要的是,我需要能够在主库初始化之前使用全局变量执行代码。

这是我的代码:

private.h


#ifndef PRIVATE_H
#define PRIVATE_H

typedef struct TEST test;

#endif


private.c (this should end up in a static library)

#include "private.h"
#include <stdio.h>

struct TEST
{
 TEST()
 {
  printf("Execute before main and have to be unavailable to the user.\n");
 }

 int a; // Can be modified by the user
 int b; // Can be modified by the user
 int c; // Can be modified by the user

} TEST;


main.c

test t;

int main( void )
{
 t.a = 0;
 t.b = 0;
 t.c = 0;

 return 0;
}

显然这段代码不起作用...但显示我需要做什么...有人知道如何使这个工作吗?我google了很多,但找不到答案,任何帮助将不胜感激。

TIA!

【问题讨论】:

    标签: c static struct static-libraries


    【解决方案1】:

    如果你使用 gcc,你可以使用 constructor 属性,

    void runs_before_main(void) __attribute__((constructor))
    {
        ...
    }
    

    来自 gcc 文档

    构造函数属性导致 自动调用的函数 在执行进入 main() 之前。 同样,析构函数属性 导致函数被调用 在 main() 之后自动 已完成或 exit() 已被调用。 具有这些属性的函数是 对初始化数据很有用 期间被隐式使用 程序的执行。

    您可以提供一个可选的整数 优先控制顺序 构造函数和析构函数 正在运行。一个较小的构造函数 优先级编号在 a 之前运行 具有更大优先级的构造函数 数字;对立关系 为析构函数成立。所以,如果你有 分配一个构造函数 资源和析构函数 释放相同的资源,两者 功能通常具有相同的 优先事项。优先事项 构造函数和析构函数 与指定的相同 命名空间范围的 C++ 对象

    如果您想对用户隐藏结构,请在头文件中声明该结构,但在 c 文件中定义它,并传递指针。举个例子:

    // foo.h
    typedef struct private_foo foo;
    foo * create_foo(void);
    void free_foo(foo * f);
    
    // foo.c
    struct private_foo {
        int i;
    }
    foo * create_foo(void){
        foo * f = malloc(sizeof(*foo));
        if (f) f->i = 1;
        return f;
    }
    ...
    

    foo-&gt;i 不能在foo.c 之外访问。

    【讨论】:

      【解决方案2】:

      如果您希望客户端代码能够使用“t.a = ...”,那么您不能隐藏结构定义。你想要的被称为不透明类型,它看起来像这样:

      公共.h: 结构 foo; set_a( struct foo *, int ); 结构 foo * new_foo(void); 主.c: #include 诠释主要(无效) { 结构 foo *k; k = new_foo(); set_a(k, 5); }

      结构定义仅对库可用。如果您不提供库源代码,则可以对库的用户完全隐藏它。

      【讨论】:

        【解决方案3】:

        C 中没有可移植的方式来确保您的代码在main() 之前运行。我要做的就是在你的库中维护一个initialised 标志,设置为false,然后在你的init 函数被调用之前拒绝做任何事情。

        如:

        static int initialised = 0;
        
        int init (void) {
            // do something.
            initialised = 1;
            return ERR_OK;
        }
        
        int all_other_functions (void) {
            if (!init)
                return ERR_NOT_INITED;
        
            // do something.
            return ERR_OK;
        }
        

        【讨论】:

        • 对句柄使用不完整类型允许编译器捕获类型错误,并避免在实现函数中进行强制转换。
        • 编译器可以仍然捕获类型错误,因为您的库代码使用正确类型的变量。或者,如果您实际上是指为您的函数提供了错误的类型,那是用户错误,他们应该承受它带来的所有困难 :-) 正如我所说,这是 one 方法,而不是唯一的办法。
        • 为什么会使用 use void * 并失去所有类型检查? typedef struct MyHiddenStruct MyHandle;我的句柄 *allocHandle();
        • 如你所愿。由于 opaque 类型是更好的方法,我将删除 void* 选项。
        猜你喜欢
        • 2012-01-12
        • 1970-01-01
        • 1970-01-01
        • 2021-07-28
        • 1970-01-01
        • 2011-03-17
        • 1970-01-01
        • 2014-10-24
        • 1970-01-01
        相关资源
        最近更新 更多