Swift memcpy 在与 ZMQ 一起使用时没有任何效果 zmq_msg_data

Swift memcpy doesn't have any effect when used with ZMQ zmq_msg_data

我一直在尝试通过构建一个名为 SwiftyZeroMQ. However, for our purposes, we require the usage of raw UDP which means we need to use ZeroMQ's Radio/Dish draft method.

的现有包装器来为 Swift 编写一个 libzmq 包装器

我已经能够成功地编写一个用于通过 Dish 套接字接收数据的包装器,但我现在正在尝试编写一个用于通过 Radio 套接字发送数据的包装器。网上似乎没有任何关于如何编写函数通过无线电套接字发送数据的资料,但我确实遇到了 this。 libzmq repo 中的这个函数测试了通过无线电套接字发送数据,所以我想为什么不尝试复制 Swift.

中的函数

这是我想出的:

Socket.swift 文件中:

     public func sendRadioMessage(_ group: String, data: NSData) throws{
            var msg = zmq_msg_t.init();
            var result : Int32;
            let flags: SocketSendRecvOption = .none
            
            
            result = zmq_msg_init(&msg);
            if (result == -1) { throw ZeroMQError.last }
        
            defer {
                // Clean up message on scope exit
                zmq_msg_close(&msg)
            }
            
            print("initial msg data = \(zmq_msg_data(&msg))")
            
            print("initial data = \(data)")
            memcpy(zmq_msg_data(&msg), (data as NSData).bytes, data.length);
            
            print("msg size = \(zmq_msg_size(&msg))")
            print("msg = \(zmq_msg_data(&msg))")
            
            result = zmq_msg_set_group(&msg, group);
            if (result == -1) { throw ZeroMQError.last }
            
            result = zmq_msg_send(&msg, self.handle, flags.rawValue);
            if (result == -1) { throw ZeroMQError.last }
            print("sent \(result) bytes")
        }
        
    }

然后像这样调用该函数:

    public func send(data: String) -> Bool{
        do{
            try radio?.sendRadioMessage(group, data: data.data(using: .utf8) as! NSData);
        }
        catch{
            print("SEND COMMUNICATION error - \(error)");
            return false;
        }
        return true;
    }

   obj.send(data: "Test Data")

这是 运行 程序时的控制台输出:

在我看来,我从 Swift 调用的 memcpy 函数实际上似乎没有做任何事情。这是因为我没有将数据有效负载正确传递给 memcpy 函数吗?我有点卡住了。

API-记录的 zmq_msg_data() 函数可以很好且安全地从传递的 ZeroMQ 消息中“读取”数据部分。

使用上下文和参数顺序:

void* memcpy(        void* dest,
               const void* src,
              std::size_t  count
              );

显示,您的代码试图将数据“存储”到 zmq_msg_t 实例中,尽​​管 ZeroMQ API 文档中有无数警告不要试图“触摸”,更不用说“直接”操作数据,而是通过使用成员函数:

Never access zmq_msg_t members directly, instead always use the zmq_msg family of functions.

这里,可能使用 rather :

int zmq_msg_init_data (   zmq_msg_t *msg, 
                               void *data, // <------- payload to load into *msg
                             size_t  size,
                        zmq_free_fn *ffn,  // ref. API details
                               void *hint  //          on this
                        );

因此说明性示例可能与此类似:

//
// Initialising a message from a supplied buffer
//
// *********************************************

void my_free ( void *data, void *hint ) // ------- a dealloc helper
{
    free ( data );
}

/* ... */

void *data = malloc ( 6 ); // -------------------- a mock-up payload data
assert ( data );
memcpy ( data, "ABCDEF", 6 );

zmq_msg_t msg;
rc = zmq_msg_init_data ( &msg, data, 6, my_free, NULL );
assert (   rc == 0
       && "INF: zmq_msg_init_data() failed, saying"
       &&  zmq_strerror ( zmq_errno() ) // ------- a non-POSIX system workaround
           );

另请注意,提议的辩护:

result = zmq_msg_init( &msg );
if ...

确实在 v2.x 和 v3.x 中给出了意义,但是在进入 v4.x 之后,它开始什么都不做,就像它在 ZeroMQ v4.3+ [=45 中一样=],正如以适当的形式和形式记录的那样:

Return value

The zmq_msg_init() function always returns zero.

可能需要进行一些版本控制和重新设计工作,以便在端口版本和实际 API 版本之间保持一致地处理此问题。