Objective-Cは元のC++ライブラリとどのようにデータ伝達を行うか
6003 ワード
最近、小さなプロジェクトが始まりました.プロジェクトでは、長接続通信用の
全体的な考え方:
少し抽象的ですが、次は上の考え方に沿って一歩一歩実現を見てみましょう.データ伝達のプロセスを示すためだけに,以下はいずれも脱敏後の簡略コードである.
まず、
コールバック関数
IMService.h
IMService.mm
これで、元の
遭遇したピットは
次に、関数内部で
Enjoy!
C++
ライブラリが必要です.(このライブラリは自己研究に属し、開発者はObjective-C
の開発経験がない).ライブラリはインタフェースファイル.h
と.a
しか提供していないため、.h
ファイルが提供するインタフェースプロトコルを使用してObjective-C
の側にデータを渡す必要がある.このプロセスはObjective-C
とC++
のライブラリデータの転送ドッキングに関連する.全体的な考え方:
Objective-C
登録コールバックからC++
の実装ファイルに移動し、チャネルがデータを受信した後、登録コールバックを通じてデータを転送する.送信された後、Objective-C
の対象パッケージを経て、使用のために送信される.少し抽象的ですが、次は上の考え方に沿って一歩一歩実現を見てみましょう.データ伝達のプロセスを示すためだけに,以下はいずれも脱敏後の簡略コードである.
まず、
C++
ライブラリが提供する.h
に何があるかを見てみましょう.//
class ImCallback
{
public:
ImCallback();
virtual ~ImCallback();
// ( 、 )
virtual void OnMessageReceived(const ImMessage *message);
};
//
class IMMANAGER_API ImManager
{
public:
ImManager();
virtual ~ImManager();
// SDK
uint32_t Init(ImCallback *callback);
};
ImCallback
はプロトコルクラスであり、OnMessageReceived
のプロトコルメソッドがデータを受信するために使用されているので、実装する必要があります.以下のImManager
クラスはチャネルインタフェースクラスであり、初期化方法uint32_t Init(ImCallback *callback)
が提供される.パラメータは、ImCallback
プロトコルに従うクラスオブジェクトです.次に、ImCallback
から継承されたクラスImCallbackImpl
を確立し、OnMessageReceived
方法を実装する.次のように#ifndef ImCallbackCpp_hpp
#define ImCallbackCpp_hpp
class ImCallbackImpl : public ImCallback
{
// ( 、 )
void OnMessageReceived(const ImMessage *message)
{
// do something
}
};
#endif
ImCallback
におけるプロトコル方法void OnMessageReceived(const ImMessage *message)
を実現した.しかし、関数の内部では現在何もしていません.次に、ImMessage
のオブジェクトmessage
を関数内部で送信する必要がある.以下にImCallbackImpl
実装の完全版を示す.#ifndef ImCallbackCpp_hpp
#define ImCallbackCpp_hpp
#include
#include "im_manager.h"
#include
typedef void (*OnMessageReceivedHandler) (const ImMessage *message);
class ImCallbackImpl : public ImCallback
{
private:
OnMessageReceivedHandler messageReceivedHandler;
public:
virtual void registerOnMessageReceivedHandler(OnMessageReceivedHandler handler) {
this->messageReceivedHandler = handler;
}
// ( 、 )
void OnMessageReceived(const ImMessage *message)
{
this->messageReceivedHandler(message);
}
};
#endif
コールバック関数
OnMessageReceivedHandler
とコールバック関数登録方法registerOnMessageReceivedHandler
を宣言した.さらに1つのプライベートメンバー変数messageReceivedHandler
は、外部に登録されたコールバックを格納し、OnMessageReceived
の方法でデータを送信するために使用される.C++
こちらのコードはreadyになっています.次にObjective-C
のドッキングコードを見てみましょう.IMService
クラスを新規作成し、.m
接尾辞を.mm
に変更します.ダイレクトコードIMService.h
#import
@class MsgModel;
NS_ASSUME_NONNULL_BEGIN
@protocol IMServiceDelegate
- (void)onMessageReceived:(HBMsgModel *)model;
@end
@interface IMService : NSObject
@end
NS_ASSUME_NONNULL_END
IMService.mm
#import "IMService.h"
#import "im_manager.h"
#include "ImCallbackCpp.hpp"
#import "HBMsgModel.h"
@interface IMService ()
@property (nonatomic, weak) id delegate;
@end
@implementation IMService {
ImManager *_imManager;
ImCallbackImpl *_imCallback;
}
- (instancetype)init {
self = [super init];
if (self) {
_imManager = CreateImManager();
_imCallback = new ImCallbackImpl;
_imManager->Init(_imCallback);
//
_imCallback->registerOnMessageReceivedHandler(hb_messageReceivedHandler);
}
return self;
}
- (void)startWith:(NSDictionary *)configuration delegate:(id)delegate {
// configuration
...
// set delegate
self.delegate = delegate;
}
void gk_messageReceivedHandler(const ImMessage *message) {
if (self.delegate && [self.delegate respondsToSelector:@selector(onMessageReceived:)]) {
MsgModel *model = [HBMsgModel new];
model.from = [NSString stringWithCString:message->from encoding:NSUTF8StringEncoding];
model.to = [NSString stringWithCString:message->to encoding:NSUTF8StringEncoding];
model.session_type = message->session_type;
model.content_type = message->content_type;
model.content_length = message->content_length;
model.message_id = [NSString stringWithCString:message->message_id encoding:NSUTF8StringEncoding];
model.timestamp = message->timestamp;
model.content = [NSString stringWithCString:message->content encoding:NSUTF8StringEncoding];
[self.delegate onMessageReceived:model];
}
}
@end
IMService.mm
では、ImCallbackImpl
の登録関数を呼び出し、gk_messageReceivedHandler
のアドレスを転送します.ImCallbackImpl
のvoid OnMessageReceived(const ImMessage *message)
メソッドは、メッセージを受信すると、コールバックによって中のmessage
データを送信します.ここで、MsgModel
クラスを新設し、データをMsgModel
オブジェクトに変換した後、
を通じて伝えました.データが必要な場所では、IMService
オブジェクトを初期化し、そのエージェントメソッドを実装すれば、チャネルから送信されたデータをリアルタイムで受け取ることができます.データを受け取った後、どのように表現したいかはUI
の設計の気持ちに従います.これで、元の
C++
ライブラリとObjective-C
ライブラリとの間のデータ転送とドッキングが完了します.間違いがあれば、指摘交流を歓迎します.遭遇したピットは
IMService.mm
のvoid gk_messageReceivedHandler(const ImMessage *message)
関数の内部でデータを伝達する過程で、頻繁なオブジェクトの作成を減らすために、私は最初に関数の外部に静的MsgModel
オブジェクトを作成しました.static MsgModel *model = [HBMsgModel new];
次に、関数内部で
model
のメンバー変数に値を割り当ててから出力します.チャネルが情報を受け取るのが頻繁ではない場合、これは良いです.その後、チャネル受信メッセージが特に頻繁に発生する場合、送信されたデータが処理に間に合わずに変更され、一部のデータが失われる場合がある.変更してから、穴を埋めることに成功しました!Enjoy!