簡體   English   中英

將全局struct變量存儲在C中的另一個全局結構中

[英]Storing a global struct variable inside another global struct in C

我試圖找出一種方法來使用嵌套的全局結構作為我的C庫的一種API命名空間。

具體來說,我想公開一個Primary '命名空間結構',它包含其他這樣的結構(例如Primary.Secondary ),它們本身包含函數指針( Primary.Secondary.a_function() )。

我已經抽象出以下(相對)簡單的例子來說明我想做的事情:

main.c

#include "Primary.h"

int main () {
  Primary.Secondary.a_function();
  return 0;
}

Primary.h

#if !defined(SECONDARY_H)
# include "Secondary.h"
#endif

struct Primary_struct {
  struct Primary__Secondary_struct  Secondary;
} extern Primary;

Primary.c

#include "Primary.h"

struct Primary_struct Primary = {
  .Secondary = Primary__Secondary
};

Secondary.h

struct Primary__Secondary_struct {
  void  (*a_function) (void);
  void  (*another_function) (void);
} extern Primary__Secondary;

Secondary.c

#include "Secondary.h"

#include <stdio.h>

void  Primary__Secondary__a_function  (void);
void  Primary__Secondary__another_function  (void);

struct Primary__Secondary_struct {
  .a_function       = Primary__Secondary__a_function,
  .another_function = Primary__Secondary__another_function
} extern Primary__Secondary;

void Primary__Secondary__a_function(void) {
  Primary.Secondary.another_function();
}

void Primary__Secondary__another_function(void) {
  printf("run!\n");
}

當我嘗試編譯它時,我遇到以下編譯器錯誤:

 > C -O0 Primary.c Secondary.c main.c
Primary.c:3:33: error: initializer element is not a compile-time constant
struct Primary_struct Primary = {
                                ^
1 diagnostic generated.

我應該注意,理想情況下, PrimaryPrimary__Secondary變量都是const 我擔心增加的復雜性會加劇這個問題......所以現在,我已經把這個方面排除在外了。

問題似乎是,由於某種原因,即使設置為const ,並且只包含編譯時出現的元素, Primary__Secondary結構也不是編譯時常量,因此在編譯時不能存儲在另一個結構中。 我可以通過在運行時設置所有接口來解決這個問題,但是......這似乎是一個非常糟糕的解決方案。 我正在尋找這個問題的任何替代解決方案,你的C-fu比我能想出的更多。

注意 :這與這個問題有關 ,但是有很大的不同,而且更具體。)

你正在努力的事情是無法做到的; 抱歉。 這是一個簡潔的例子:

#include <stdio.h>

int a = 5;
int b = a;

int main(int argc, char *argv[])
{
  printf("Hello, world!\n"); 
  return 0;
}

編譯此代碼會出錯:

main.c:4: error: initializer element is not constant

因為編譯器不知道如何在編譯時將賦值int b = a 這就是語言的工作方式!

你的代碼中有一些奇怪的符號 - 我把它們轉換成更正統的形式。 另外,作為一般規則,避免在名稱中使用雙下划線; 在C ++中,這是絕對必要的。 您還需要使用指向嵌入式結構的指針 - 然后代碼將運行:

Primary.h

//Primary.h:
#ifndef PRIMARY_H
#define PRIMARY_H

#include "Secondary.h"

struct Primary_struct {
  struct Primary_Secondary_struct *Secondary;
};

extern struct Primary_struct Primary;

#endif // PRIMARY_H

Secondary.h

//Secondary.h:
#ifndef SECONDARY_H
#define SECONDARY_H

struct Primary_Secondary_struct {
  void  (*a_function)(void);
  void  (*another_function)(void);
};

extern struct Primary_Secondary_struct Primary_Secondary;

#endif // SECONDARY_H

Primary.c

//Primary.c:

#include "Primary.h"

struct Primary_struct Primary = {
  .Secondary = &Primary_Secondary
};

Secondary.c

//Secondary.c:

#include "Secondary.h"
#include "Primary.h"
#include <stdio.h>

void Primary_Secondary_a_function(void);
void Primary_Secondary_another_function(void);

struct Primary_Secondary_struct Primary_Secondary = {
  .a_function       = Primary_Secondary_a_function,
  .another_function = Primary_Secondary_another_function
};

void Primary_Secondary_a_function(void) {
  Primary_Secondary.another_function();
  printf("hide!\n");
}

void Primary_Secondary_another_function(void) {
  printf("run!\n");
}

main.c中

//main.c:
#include "Primary.h"

int main () {
  Primary.Secondary->a_function();
  return 0;
}

這會產生:

run!
hide!

我最終選擇了運行時方法,至少目前是這樣。 我可能稍后嘗試一種指針方法(由Jonathan Leffler建議),看看我是否最終得到了一個不那么復雜/更易於理解的代碼庫......但是現在這種方法很有用。

我使用clang (和gcc )的__attribute__((constructor))擴展來在運行時設置結構的關系; 使用main()一些代碼可以更方便地實現(但不太干凈main()

我會提供一些解釋,但這是凌晨4點......嘿。 我整天都花在這上面,<

main.c

#include "Package.h"

int main () {
  Package.One.a_function();
  Package.One.another_function();

  Package.Two.a_function();
  Package.Two.another_function();

  return 0;
}

Package.h

#define PACKAGE_H

#if !defined(ONE_H)
# include "One.h"
#endif
#if !defined(TWO_H)
# include "Two.h"
#endif

// It seems this is broken, at least in `clang`
// #if __has_feature(attribute_constructor)
# define constructor __attribute__((constructor))
// #endif

struct Package_struct {
  struct Package__One_struct  One;
  struct Package__Two_struct  Two;
};

struct Package_struct extern Package;

Package.c

#include "Package.h"

struct Package_struct Package = {};

One.h

#define ONE_H

struct Package__One_struct {
  void  (*a_function)       (void);
  void  (*another_function) (void);
};

struct Package__One_struct extern Package__One;

One.c

#include "One.h"
#include "Package.h"

#include <stdio.h>

void  Package__One__a_function        (void);
void  Package__One__another_function  (void);

struct Package__One_struct Package__One = {
  .a_function       = Package__One__a_function,
  .another_function = Package__One__another_function
};
void constructor Package__register_One(void) {
  Package.One = Package__One; }

void Package__One__a_function(void) {

  Package.One.another_function();

}

void Package__One__another_function(void) {

  printf("one!\n");

}

Two.h

#define TWO_H

struct Package__Two_struct {
  void  (*a_function)       (void);
  void  (*another_function) (void);
};

struct Package__Two_struct extern Package__Two;

Two.c

#include "Two.h"
#include "Package.h"

#include <stdio.h>

void  Package__Two__a_function        (void);
void  Package__Two__another_function  (void);

struct Package__Two_struct Package__Two = {
  .a_function       = Package__Two__a_function,
  .another_function = Package__Two__another_function
};
void constructor Package__register_Two(void) {
  Package.Two = Package__Two; }

void Package__Two__a_function(void) {

  Package.Two.another_function();

}

void Package__Two__another_function(void) {

  printf("two!\n");

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM