【问题标题】:Swift memcpy doesn't have any effect when used with ZMQ zmq_msg_dataSwift memcpy 与 ZMQ zmq_msg_data 一起使用时没有任何效果
【发布时间】:2021-03-29 16:41:48
【问题描述】:

我一直在尝试通过构建一个名为 SwiftyZeroMQ 的现有包装器来为 Swift 编写一个 libzmq 包装器。但是,出于我们的目的,我们需要使用原始 UDP,这意味着我们需要使用 ZeroMQ 的Radio/Dish draft method

我已经能够成功地编写一个用于通过 Dish 套接字接收数据的包装器,但我现在正在尝试编写一个用于通过 Radio 套接字发送数据的包装器。网上似乎没有任何关于如何编写函数以通过 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 函数吗?我有点卡住了。

【问题讨论】:

  • 这段代码不是C++
  • @PaulMcKenzie 我使用的库有一个 C++ 核心,我与之交互的函数也是用 C++ 编写的。我链接的示例函数也是用 C++ 编写的。我的代码基于那个 C++ 函数。
  • 那么应该很容易看出memcpy需要什么作为参数。
  • @PaulMcKenzie 是的,我已经查看了 memcpy 函数参数。我传递的参数与它在您的链接上的状态相关。
  • memcpy 没有任何问题。它只知道去源地址并将字节复制到目标地址——不多也不少。 memcpy 不关心参数,不检查它们的有效性等。它会盲目地接受你给它的东西,把它解释为地址,然后复制。传递正确的论点是你的责任。对于任何基于 C++ 的函数,您都会遇到同样的问题,而不仅仅是 memcpy

标签: c++ objective-c swift zeromq memcpy


【解决方案1】:

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

使用上下文&参数顺序:

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

表明,您的代码尝试将数据“存储”到 zmq_msg_t-实例中,尽​​管 ZeroMQ API 文档中有无数警告不要尝试“触摸”,但越少“直接”操作数据,但使用成员函数:

永远不要直接访问 zmq_msg_t 成员,而是始终使用 zmq_msg 系列函数。

这里,可能使用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+ API 中,正如以适当的形式和形式记录的那样:

返回值

zmq_msg_init() 函数总是返回零。

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

【讨论】:

  • 这确实解决了消息没有任何数据的问题,但它并没有解决我的总体目标。我的 python 程序没有收到任何消息。我认为这是因为在盘子方面(我的 python 程序),它试图通过仅使用接收函数而不使用消息来接收数据。你知道我如何在不使用消息的情况下发送数据吗?
  • 很高兴它帮助了@RichardWei
猜你喜欢
  • 2013-05-12
  • 2020-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 2021-01-30
  • 2018-05-27
  • 2018-06-14
相关资源
最近更新 更多