0

我有三个 *.h 文件:

啊:

<some types>
extern sometype1 somevar1;

乙:

<some types>
extern sometype2 somevar2;

频道:

<some types>
extern sometype3 somevar3;

我有 Dc 文件:

#include "A.h"
#include "B.h"
#include "C.h"

int freethemall()
{
    TheFunctionFromAhFileForFreeingTheSomevar1Resources();
    TheFunctionFromBhFileForFreeingTheSomevar2Resources();
    TheFunctionFromChFileForFreeingTheSomevar3Resources();
}

这个项目是某种框架。

有时我不需要所有模块——例如 A、B 或 C,我只需要 A 和 B 模块。但是我的框架初始化的结构如下:

#include "A.h"
#include "B.h"
<Frameworkname>Init();

<do some code here>

<Frameworkname>Free();

因此,从每个模块调用所有 Free 函数而不是仅调用一个 ...Free() 函数是非常非常不舒服的:

#include "A.h"
#include "B.h"
<Frameworkname>Init();

<do some code here>

<Frameworkname><modulename1>Free();
<Frameworkname><modulename2>Free();
..
<Frameworkname><modulenameN>Free();

在这种情况下,N 只有 2,但我有大约 20 个模块,因此将它们全部计算在内对程序员不友好。

如何更改 freethemall() 函数以仅调用我使用和包含的模块的析构函数?请注意,Dh 包含该功能,并且有很多模块包含 Dh

PS 如果需要,我可以在每个其他模块中包含 Dh 模块。

作为解决它的另一种方法,我需要一个在模块完成之前调用的函数,就像在最后的 Delphi 语言中一样:

Unit ...

Finalization
   Callme;
End.

无需从 freethemall() 调用它,但它是解决此问题的某种线索。

谢谢你的任何建议。

4

5 回答 5

1

2种方式:

  1. “hack”是在每个模块中执行#define,或者如果您无权访问模块的代码,请执行 #define USE_A 和 ifdef USE_A 以实际包含标头。因此,更改#define 将确定是否包含标头,并且释放函数将检查相同的定义。

  2. 正确的方法是拥有一个“注册”您需要释放的项目的功能。一个指针数组。所以当你创建每一个时,你添加它的指针或一个指向将它释放到数组的函数的指针,然后当你需要释放时,你只需循环遍历数组并在那里释放每个。

于 2013-11-11T16:58:37.030 回答
0

您可以使用 Header Guards *1(无论如何都缺少)来解决您的问题:

通过像这样修改标题来添加标题卫士:

啊:

#ifndef _A_H
#define _A_H

<some types>
extern sometype1 somevar1;

#endif

乙:

#ifndef _B_H
#define _B_H

<some types>
extern sometype2 somevar2;

#endif

频道:

#ifndef _C_H
#define _C_H

<some types>
extern sometype3 somevar3;

#endif

我有 Dc 文件:

#include "A.h"   /* \                                            */
#include "B.h"   /*  \                                           */
#include "C.h"   /*   + <--- comment in/out here what is needed. */
...              /*  /                                           */
#include "_n_.h" /* /                                            */


int freethemall()
{
    #ifdef _A_H
    TheFunctionFromAhFileForFreeingTheSomevar1Resources();
    #endif

    #ifdef _B_H
    TheFunctionFromBhFileForFreeingTheSomevar2Resources();
    #endif

    #ifdef _C_H
    TheFunctionFromChFileForFreeingTheSomevar3Resources();
    #endif

    ...

    #ifdef __n__H
    TheFunctionFromChFileForFreeingTheSomevar_n_Resources();
    #endif

    return 0;
}

通过在Header Guards 的定义中注释/注释#include行,各种字段用于控制哪些代码行被停用/激活。 D.c*.hfreethemall()


*1 要了解 Header Guard,请单击此处并向下滚动答案

于 2013-11-11T18:50:32.927 回答
0

这就是他们创建 c++ 的原因。过载机制在这里很容易解决您的问题。但是由于您必须在 C 中执行此操作,所以我知道的唯一方法是使用位域

Free(uint32 bitfield){

int i,masklen =32;

for (i=0;i<masklen;i++)
{
  if (bitfield & 1<<i)
    // call free for module i
    // you can have an array of function pointers so that you easily get the right
    // free function each time 
} 
}

如果您需要更多模块,Tis 将允许您使用 32 个模块,您需要不同类型的位域

于 2013-11-11T16:56:50.333 回答
0

您可以创建初始化函数,该用户需要在程序启动期间调用。该函数将传递用户将使用哪些模块。您的库将存储该信息,并在关闭时调用适当的函数。

例子:

/* Header file */

enum SmlModule {
    SML_RASTER = 1,
    SML_EVENT  = 2,
    SML_TIME   = 4
}

int sml_init(int modules);

然后在程序中:

int main ()
{
    sml_init(SML_RASTER | SML_TIME);
    (...)
    return 0;
}

例如,SDL库使用此方法,请参阅SDL_Init

于 2013-11-11T17:11:01.570 回答
-1

我认为你想要的是不可能的。

在 C++ 中,这是可能的,因为对象的声明(无论是在头文件中还是在模块中)可以导致代码被执行,但在 C 中却不能。

如果你这样做

main.h:

typedef struct {
    void (*init)(void) ;
    void (*exit)(void) ;
    } MODULE ;

A.h:
extern MODULE A ;

B.h
extern MODULE B ;

main.c:

#include    "main.h"
#include    "A.h"
#include    "B.h"

MODULE modules[] = {
&A,
&B,
0,
} ;

然后在 init,exit 阶段迭代模块数组,为这些阶段调用适当的函数。

这样你只需要维护 2 行。这是我能想到的最紧凑和可维护的方式。

于 2013-11-11T17:02:53.950 回答