【问题标题】:Providing a callback function as a specific pointertype提供回调函数作为特定的指针类型
【发布时间】:2013-10-22 15:16:03
【问题描述】:

我目前正在 Mac 上的 Objective-C 中的服务器上工作,该服务器在特定端口上侦听传入数据。它已经适用于基于 NSStreams 的双向未加密数据传输。

在下一步中,我想通过 SSL/TLS 保护连接。目前我正在关注他们在this 页面上的文档中描述的苹果方法。在概述中,他们描述了建立 SSL 连接的典型序列。

我现在失败的地方是我必须给出表单的指针

typedef OSStatus (*SSLReadFunc) (
   SSLConnectionRef connection,
   void *data,
   size_t *dataLength
);

在为 SSL-Connection 设置 I/O 功能的方法中,以便负责的对象可以调用这些方法来读取和写入我的流。这两个方法我已经写好了

// Called by the secure transport to write data on the stream
-(OSStatus)sslWriteCallbackFunction:(SSLContextRef)context data:(const void *)data dataLength:(size_t)dataLength sizeOfProcessedData:(size_t *)processed{
    processed = (size_t *)[_writeStream write:data maxLength:dataLength];
    if (processed < 0)
        return errSSLProtocol;
    else if (processed==0)
        return 0;
    else
        return errSSLWouldBlock;
}

// Called by the secure transport to read data from the stream
-(OSStatus) sslReadCallbackFunction:(SSLContextRef)context data:(const void *)data dataLength:(size_t)dataLength{
    uint8_t buffer[dataLength];
    NSInteger err = [_readStream read:buffer maxLength:dataLength];

    if (err < 0)
        // Error
        return errSSLProtocol;
    else if (err==0)
        // All bytes have been read
        return 0;
    else
        // err corresponds to the number of bytes read, so there are still bytes available
        dataLength = err;
        return errSSLWouldBlock;
} 

并希望将它们设置在带有签名的方法中

OSStatus SSLSetIOFuncs (
   SSLContextRef context,
   SSLReadFunc readFunc,
   SSLWriteFunc writeFunc
);

方法sslReadCallbackFunction分别通过readFunc和write方法传递。

现在,我怎样才能创建指向上述表单的两种方法之一的指针。我已经尝试了很多,如果有人可以帮助我或指出正确的方向,我将非常感激。我用了选择器,只是在方法名前面加了一个&amp;,用的是self的方法,....

感谢任何帮助,请注意我是 Objective-C 的新手 ;)

【问题讨论】:

    标签: objective-c pointers networking ssl


    【解决方案1】:

    API 需要一个指向具有给定签名的 C 函数的指针,而不是 Objective-C 方法。如果您仍想在方法而不是函数中处理回调,则需要使用“trampoline”函数。这是一个简单地调用 Objective-C 方法的小函数。回调函数通常包含一个用户上下文指针,它提供给 API 并传递给函数。这很方便,因为您可以传入 self 并使用它轻松地向正确的 ObjC 实例发送消息。像这样的:

    OSStatus MySSLReadCallbackFunction(SSLConnectionRef connection, void *data, size_t *ioDataLength)
    {
        MySSLClass *obj = (__bridge MySSLClass *)connection
        return [obj sslReadFromConnection:connection intoBuffer:data length:ioDataLength];
    }
    
    // In the function that sets this stuff up:
    SSLSetConnection(context, (__bridge void *)self);
    SSLSetIOFuncs(context, MySSLReadCallbackFunction, MySSLWriteCallbackFunction);
    

    Mark Dalrymple 在他的博客上有一个 good post 来讨论这个一般性问题。

    请注意,正如那篇文章的 cmets 中所述,可以获取指向实现 ObjC 方法的底层 C 函数的指针。但是,实现 ObjC 方法的函数有两个“隐藏”参数(self_cmd),因此您不能强制它们具有此类 API 的正确签名。

    【讨论】:

    • 我认为您可以为此目的使用 SSLConnectionRef。它是一个不透明的指针,可以与 SSLContextRef:SSLSetConnection(context, (__bridge void *)self); 关联,并且正是传递给回调函数,所以 MySSLClass *obj = (__bridge MySSLClass*)connection; 应该可以工作。
    • 谢谢马丁。从我浏览的文档中并不清楚这一点,而且我对这个 API 没有直接经验。我编辑了我的答案以包括这个。
    猜你喜欢
    • 1970-01-01
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2014-01-04
    • 2020-11-11
    • 1970-01-01
    • 2016-10-10
    相关资源
    最近更新 更多