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

╄→尐↘猪︶ㄣ 提交于 2021-01-29 20:31:11

问题


I've been trying to write a libzmq wrapper for Swift by building off of an existing wrapper called SwiftyZeroMQ. However, for our purposes, we require the usage of raw UDP which means we need to use ZeroMQ's Radio/Dish draft method.

I've been able to successfully write a wrapper for receiving data via the Dish socket but I'm now trying to write a wrapper for sending data via the Radio socket. There doesn't seem to be any stuff online regarding how to write a function to send data via the Radio socket but I did come across this. This function in the libzmq repo tests the sending of data via the radio socket so I figured why not try and replicate the function in Swift.

Here's what I've come up with:

Inside the Socket.swift file:

     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")
        }
        
    }

and that function is then called like this:

    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")

This is the console output when running the program:

It seems to me then that the memcpy function that I'm calling from Swift doesn't actually seem to be doing anything. Would this be due to the fact that I'm not passing the data payload properly to the memcpy function? I'm a bit stuck.


回答1:


The API-documented zmq_msg_data() function is fine & safe to "read" a data-part from a delivered ZeroMQ message.

The context of use & the order of parameters :

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

shows, that your code tries to "store" data into a zmq_msg_t-instance, in spite of countless warnings in the ZeroMQ API documentation not to ever attempt to "touch", the less to manipulate data "directly", but by using member functions :

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

Here, possibly using 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
                        );

So the illustrative example might be something alike 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
           );

Also note, that a proposed defense of :

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

did gave a sense in v2.x & v3.x, yet after moving into v4.x, it started to do nothing , as it keeps in ZeroMQ v4.3+ API, as is documented in due form and shape :

Return value

The zmq_msg_init() function always returns zero.

Some version-control and redesign efforts might be needed so as to keep handling this consistently between the port-version and the actual API-version.



来源:https://stackoverflow.com/questions/65367000/swift-memcpy-doesnt-have-any-effect-when-used-with-zmq-zmq-msg-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!