C/Cygwin:将htoll()从MacOS/Unix移植到Windows Cygwin

332nm8kg  于 2022-09-21  发布在  Mac
关注(0)|答案(2)|浏览(262)

我正在将我的应用程序从MacOS平台移植到Windows平台(这里是Cygwin)。我遇到了网络函数ntohll()和htonll()的问题,而ntohl()/htonl()和ntohs()/htons()似乎工作正常

/* LACK OF ntohll() function definition on Cygwin */
    // convert int64 from network to host representation
    *int64 = ntohll(network_int64);

    /* SEEMS TO WORK CORRECTLY */
    // convert int32 from network to host representation
    *int32 = ntohl(network_int32);

更新:这个怎么样?

uint64_t ntohll(uint64_t network_num64) {

    uint32_t network_num32[2];
    uint32_t host_num32[2];
    uint64_t host_num64;

    memcpy(network_num32, &network_num64, sizeof(network_num64));
    host_num32[0] = ntohl(network_num32[0]);
    host_num32[1] = ntohl(network_num32[1]);

    memcpy(&host_num64, host_num32, sizeof(host_num64));
    return host_num64;
}

uint64_t htonll(uint64_t host_num64) {

    uint32_t host_num32[2];
    uint32_t network_num32[2];
    uint64_t network_num64;

    memcpy(host_num32, &host_num64, sizeof(host_num64));
    network_num32[0] = htonl(host_num32[0]);
    network_num32[1] = htonl(host_num32[1]);

    memcpy(&network_num64, network_num32, sizeof(network_num64));
    return network_num64;
}
r1wp621o

r1wp621o1#

我已经编写了自己的htonll()和ntohll()函数,它们可以在uint64_t(64位数字)的情况下解决Cygwin的字符顺序问题。我认为它应该是有效的,但也希望你证明它真的是一个很好的解决方案。

我编写了以下函数:1.isBigEndian()和isLittleEndian()-检查当前主机使用的是大端还是小端2.然后假设网络字节顺序为大端。因此,如果在当前主机上有低端字符顺序,我将需要交换字符顺序,如果是大端字符顺序,我只能使用在htonll()/ntohll()参数的数字中收到的字符顺序。3.我编写了一个函数,将64位数字的字节顺序从大到小分别交换到小或大,即swapEndianness()

以下是所有代码:

bool isBigEndian() {
    int n = 1;
    // little endian if true
    if(*(char *)&n == 1) {
        return false;
    }
    return true;
}

bool isLittleEndian() {
    return  !(isBigEndian());
}

uint64_t swapEndianness(uint64_t num) {

    uint64_t b0, b1, b2, b3, b4, b5, b6, b7;
    uint64_t swapped_num;

    b0 = (num & 0x00000000000000ff) << 56u;
    b1 = (num & 0x000000000000ff00) << 40u;
    b2 = (num & 0x0000000000ff0000) << 24u;
    b3 = (num & 0x00000000ff000000) << 8u;
    b4 = (num & 0x000000ff00000000) >> 8u;
    b5 = (num & 0x0000ff0000000000) >> 24u;
    b6 = (num & 0x00ff000000000000) >> 40u;
    b7 = (num & 0xff00000000000000) >> 56u;

    swapped_num = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7; 

    return swapped_num;
}

uint64_t htonll(uint64_t host_num64) {

    if(isLittleEndian()) {
        // swap little endian to big endian (network byte order)
        return swapEndianness(host_num64);
    }
    return host_num64;
}

uint64_t ntohll(uint64_t network_num64) {

    if(isLittleEndian()) {
        // swap big endian (network byte order) to little endian
        return swapEndianness(network_num64);
    }
    return network_num64;
}

我还用以下代码测试了上面的代码:

static void test_swap_endianness(void) {

    uint64_t number = 0x1123456789ABCDEF;
    printf("hex number = 0x%" PRIx64 "n", number);

    uint64_t swappedNumber = swapEndianness(number);
    printf("hex swapped number: 0x%" PRIx64 "n", swappedNumber);
}

并在交换uint64_t编号的字节顺序时实现正确输出:

=========== test_swap_endianness ==============
hex number = 0x1123456789abcdef
hex swapped number: 0xefcdab8967452311
8ehkhllq

8ehkhllq2#

这是我的解决方案。这是通过对整数调用htonll和ntohll两次并交换结果顺序来实现的。请注意,这需要endian.h,因为它检查字节顺序以确保与大端系统兼容。


# if __BYTE_ORDER == __BIG_ENDIAN

    #ifndef htonll
        #define htonll(num) (num)
    #endif
    #ifndef ntohll
        #define ntohll(num) (num)
    #endif

# else

    #ifndef htonll
        #define htonll(num) ({                                      
            uint64_t _num = num;                                    
            ((((uint64_t) htonl(_num)) << 32) | htonl(_num >> 32)); 
        })
    #endif
    #ifndef ntohll
        #define ntohll(num) ({                                      
            uint64_t _num = num;                                    
            ((((uint64_t) ntohl(_num)) << 32) | ntohl(_num >> 32)); 
        })
    #endif

# endif

相关问题