0

次のような古い C コードがあります。

#include <stdio.h>
#include <strings.h>
main()
{

    FILE *output;

    struct socket_cpacket
    {
        char    type;                                /* CP_SOCKET */
        char    version;
        char    udp_version;                         /* was pad2 */
        char    pad3;
        unsigned socket;
    };

    struct socket_cpacket sockPack;

    bzero(&sockPack,sizeof(sockPack));
    sockPack.type = 27;
    sockPack.version = 4;
    sockPack.udp_version = 10;
    sockPack.pad3 = 0;
    sockPack.socket = 0;

    output = fopen("/tmp/sockPack.bin", "wb");
    fwrite(&sockPack, sizeof(sockPack), 1, output);
}

この機能を obj-c で複製したいと思い、NSCoding プロトコルを使用する道を歩み始めました。

CP_Socket.h

#import <Foundation/Foundation.h>

@interface CP_Socket : NSObject <NSCoding>
{
@private
    char type;
    char version;
    char udp_version;
    char pad3;
    unsigned int socket;
}

@property (readonly) char type;
@property (readonly) char version;
@property (readonly) char udp_version;
@property (readonly) char pad3;
@property unsigned int socket;

typedef enum {
    mTYPE = 27,
    mVERSION = 4,
    mUDP_VERSION = 10,
} cpSocketEnum;

@end

そして CP_Socket.m

#import "CP_Socket.h"

@implementation CP_Socket

#pragma mark ======== properties =========

@synthesize  type;
@synthesize  version;
@synthesize  udp_version;
@synthesize  pad3;
@synthesize  socket;


- (id)init {
    NSLog(@"init");

    if( !( self = [super init] ) )
        return nil;

    type = mTYPE;
    version = mVERSION;
    udp_version = mUDP_VERSION;
    pad3 = 0;
    socket = 0;

    return self;
}

#pragma mark ======== Archiving and unarchiving methods =========
//
// Archives and Serializations Programming Guide for Cocoa
// http://bit.ly/PAaRsV
//
// NSCoding Protocol Reference
// http://bit.ly/PAb1Rd
//

- (void)encodeWithCoder:(NSCoder *)coder
{
    NSLog(@"encodeWithCoder");

    [coder encodeBytes:[self type] length:1 forKey:@"type"];
    //[coder encodeBytes:[self version] length:1 forKey:@"version"];
    //[coder encodeBytes:[self udp_version] length:1 forKey:@"udp_version"];
    //[coder encodeBytes:[self pad3] length:1 forKey:@"pad3"];
    //[coder encodeInt:[self socket] forKey:@"socket"];

}

- (id)initWithCoder:(NSCoder *)coder
{
    NSLog(@"initWithCoder");
}
@end

最初の問題、 [coder encodeBytes:[self type] length:1 forKey:@"type"]; 警告をスローします。型「const uint8_t *」のパラメーターに「char」を送信する、互換性のない整数からポインターへの変換。

char をエンコードするにはどうすればよいですか?

[coder encodeInt:[self type] forKey:@"type"]; を試しました。しかし、char != int.

コードがどのように機能するかをさらに理解するためにコードを使用します。obj-c コードが生成するファイルは 280 バイトで、ファイルの中を見ると、名前がマングルされたクラス識別子のように見えます。

NSKeyedArchiver と NSArchiver を試してみましたが、同じ結果が得られました。

ここからどこへ行けばいいのかわからない。C コードは 8 バイトのファイルを生成します。NSCoding プロトコルのような OO のいくつかを使用しながら、obj-c コードで同じことを行いたいと思います。

これを機能させるには、NSCoder オブジェクトを拡張する必要があるように感じます。

どんな助けでも大歓迎です。

4

2 に答える 2

0

私は NSCoding についてあまり知りませんが、obj C は C とうまく相互運用します。既存のコードを取得し、params を使用して関数に入れて呼び出します。

于 2012-09-17T21:28:07.670 に答える
0

の最初の引数encodeBytes:length:forKey:は、エンコードするバッファへのポインタであると想定されるため、ivar のアドレスを取得します。

[coder encodeBytes:&type length:1 forKey:@"type"];

または、一時変数を作成し、その中にプロパティ アクセスの結果を入れて、そのアドレスを取得します。

を使用しencodeInt:forKey:ても (キャストを使用して) 動作するはずですが、データ ファイルのサイズが大きくなります。

あなたが本当にしたいのであれば、確かNSCoderにカテゴリを拡張することができます:

@implementation NSCoder (BTEncodeChar)
- (void)BTencodeChar: (char)c forKey: (NSString *)key
{
    [self encodeBytes:&c length:1 forKey:key];
}
@end
于 2012-09-17T20:55:16.513 に答える