5

私の毎日のばかげた質問に戻ります。今日、構造体を NSArray に入れようとしています。それは簡単です。NSData でラップします。私のことを知っていれば、これからコードを目にすることになるでしょう。この例では、Wavefront OBJ から構造体に頂点ラインをロードし、それを配列に貼り付けています。

        NSArray *verticeLineParts = [currentLine componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        Coordinate c = CoordinateMake([[verticeLineParts objectAtIndex:1] floatValue],
                                      [[verticeLineParts objectAtIndex:2] floatValue],
                                      [[verticeLineParts objectAtIndex:3] floatValue]);
        [vertices addObject:[[NSData alloc] initWithBytes:&c length:sizeof(c)]];

これはうまくいくようです。出力の最初のいくつかのオブジェクト:

2010-10-18 14:18:08.237 ObjLoader[3778:207] (
    <5d1613bd 13f3da3f 8ac745bd>,
    <f04c28bd 13f3da3f d88048bd>,
    <649427bd d61ddb3f d88048bd>,
    <477625bd d845db3f d88048bd>,
    <4c1722bd 1668db3f d88048bd>,

配列からそれらを引き出した後にそれらを印刷することになると、それほど多くはありません。問題のコード:

for (int i = 0; i < [vertices count]; i++) {
    Coordinate c;
    fillCoordinateFromData(c, [vertices objectAtIndex:i]);
    NSLog(@"%@", CoordinateToNSString(c));
}

[snip]

void fillCoordinateFromData(Coordinate c, NSData *d) {
    void *bytes = malloc(12);
    [d getBytes:bytes];
    memcpy((void *)&c, &bytes, 12);
    free(bytes);
}

もちろん、問題のある出力:

2010-10-18 14:22:00.692 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000
2010-10-18 14:22:00.693 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000
2010-10-18 14:22:00.694 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000
2010-10-18 14:22:00.695 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000
2010-10-18 14:22:00.695 ObjLoader[3825:207] 9.885923, -6.837428, 0.000000

これは、魔法使いの見習いのような、C の魔法使いではない誰かが C の魔法使いを試みたことが原因だと思います。これは 99 度の魔法使いには明らかなはずですが、誰かがこれを行うためのより現代的な方法を提案できる場合はお知らせください。

ありがとう、ウィル

4

1 に答える 1

10
void fillCoordinateFromData(Coordinate c, NSData *d) {

cこれは値渡しです。この関数の変更はc呼び出し元に反映されません。

代わりにポインタ (参照) で渡す必要があります。

fillCoordinateFromData(&c, [vertices objectAtIndex:i]);

void fillCoordinateFromData(Coordinate* pc, NSData *d) {
    void *bytes = malloc(12);
    [d getBytes:bytes];
    memcpy((void *)c, &bytes, 12);
    free(bytes);
}

ただし、座標を返すだけの方がよいでしょう。

Coordinate c = getCoordinateFromData([vertices objectAtIndex:i]);

Coordinate getCoordinateFromData(NSData* d) {
  Coordinate c;
  [d getBytes:&c];   // and let's not waste time allocating 12 bytes.
  return c;
}

ところで、慣例により、構造体はNSDataではなく NSValue でラップされます。

[vertices addObject:[NSValue valueWithBytes:&c withObjCType:@encode(Coordinate)]];

Coordinate getCoordinateFromData(NSValue* d) {
  Coordinate c;
  [d getValue:&c];
  return c;
}
于 2010-10-18T19:34:10.867 に答える