[英]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.
我應該注意,理想情況下, Primary
和Primary__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:
#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:
#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:
#include "Primary.h"
struct Primary_struct Primary = {
.Secondary = &Primary_Secondary
};
//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:
#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.