Linux 下常见的 C 标准库为 glibc,可以通过宏 __GLIBC__
识别,但是 musl libc 没有提供类似 __MUSL__
这样的宏来进行标记(官方解释),那么应该怎么在 C 代码中识别呢?最好不要因为这个写两套代码。
起因就是 glibc 和 musl libc 中 struct in6_addr
的成员名不一样导致编译错误。
/* musl libc 的实现 */
struct in6_addr {
union {
uint8_t __s6_addr[16];
uint16_t __s6_addr16[8];
uint32_t __s6_addr32[4];
} __in6_union;
};
/* glibc 实现 */
#if !__USE_KERNEL_IPV6_DEFS
/* IPv6 address */
struct in6_addr
{
union
{
uint8_t __u6_addr8[16];
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
} __in6_u;
#define s6_addr __in6_u.__u6_addr8
#ifdef __USE_MISC
# define s6_addr16 __in6_u.__u6_addr16
# define s6_addr32 __in6_u.__u6_addr32
#endif
};
#endif /* !__USE_KERNEL_IPV6_DEFS */
目前一个不怎么靠谱的想法是排除法。可以通过宏识别 glibc 、eglibc 和 uclibc 。算上 musl libc 常见的大概也就这四个吧?那么通过宏识别到都不是 glibc 、eglibc 和 uclibc 后,就默认是 musl libc 。但是说实话不太靠谱,因为万一还有别的库就容易出问题。
解决了,两个库定义了同一个宏类似 s6_addr16
来统一访问结构体成员。不需要做额外的工作了。
1
favourstreet 2021-01-09 18:26:30 +08:00 via Android
人家成员名前面加了一个下划线还不够,加了两个下划线,楼主你好最好解释一下为什么要“把手伸进去”倒腾一个摆明了不给外人看的东西?
|
2
minami 2021-01-09 18:33:08 +08:00 1
成员名不一样,但内存长度是一样的吧,自己重定义下结构体就可以了
|
3
c137rick OP @favourstreet #1 原因就是要分别识别 IPV6 每一个 bit 用来做成前缀树进行网段匹配,所以需要 `in6_addr.__in6_union.__s6_addr[16]`。不过这么一说确实这不应该是我了解的,按照二楼的方法重新定一个结构体就行了。
|