如何将Windows SOCKADDR_BTH的C语言转换复制到Rust中的SOCKADDR?

我正在使用Winsock2(但很高兴使用任何其他库)在Rust的Windows上编写Bluetooth实用程序,但遇到了障碍.以下是Windows Bluetooth Connection Sample的C示例,仅供参考:

SOCKADDR_BTH SockAddrBthServer;
# code to set SockAddrBthServer vals in here 
connect(LocalSocket, (struct sockaddr *) &SockAddrBthServer, sizeof(SOCKADDR_BTH));

结构的定义如下:

typedef struct _SOCKADDR_BTH
{
    USHORT      addressFamily;  // Always AF_BTH
    BTH_ADDR    btAddr;         // Bluetooth device address
    GUID        serviceClassId; // [OPTIONAL] system will query SDP for port
    ULONG       port;           // RFCOMM channel or L2CAP PSM
} SOCKADDR_BTH, *PSOCKADDR_BTH;


typedef struct sockaddr {

#if (_WIN32_WINNT < 0x0600)
    u_short sa_family;
#else
    ADDRESS_FAMILY sa_family;           // Address family.
#endif //(_WIN32_WINNT < 0x0600)

    CHAR sa_data[14];                   // Up to 14 bytes of direct address.
} SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;

如何在Rust中从上面的连接线复制(struct sockaddr *)& SockAddrBthServer?到目前为止,我正在使用winapi,user32和ws2_32条板箱.

这是connect function from the ws2_32 crate的Rust版本.

pub unsafe extern "system" fn connect(s: SOCKET, name: *const SOCKADDR, namelen: c_int) -> c_int
最佳答案
您正在考虑问题.如果Windows表示将SOCKADDR_BTH指针强制转换为SOCKADDR指针很酷,则只需执行此操作即可.在Rust中,您必须添加一个额外的强制类型转换以离开安全的引用世界,并获得原始指针,然后可以将其强制转换为所需的任何内容:

use std::mem;

struct SomeErrorType;

fn example(LocalSocket: SOCKET) -> Result<SOCKADDR_BTH, SomeErrorType> {
    unsafe {
        let SockAddrBthServer: SOCKADDR_BTH = mem::uninitialized();
        let retval = connect(
            LocalSocket,
            &SockAddrBthServer as *const SOCKADDR_BTH as *const SOCKADDR,
            mem::size_of::<SOCKADDR_BTH>() as i32,
        );
        // PERFORM REAL ERROR CHECKING HERE
        if retval == 42 {
            Ok(SockAddrBthServer)
        } else {
            Err(SomeErrorType)
        }
    }
}

(未经测试,因为我没有Windows机器)

在后台,这仅在SOCKADDR_BTH的初始成员与SOCKADDR的成员完全匹配时才有效.

转载注明原文:如何将Windows SOCKADDR_BTH的C语言转换复制到Rust中的SOCKADDR? - 代码日志