2010-11-09 12 views
1

Je passe avec succès un nombre de 64 bits d'un client objC à un client java, mais je suis incapable d'envoyer à un client objC. Code /* * Récupère un numéro double (64 bits) du flux. */ double getDouble() privé lance IOException { octet [] buffer = getBytes (8);ObjC obtient le numéro de 64 bits du flux

long bits = 
      ((long)buffer[0] & 0x0ff) | 
      (((long)buffer[1] & 0x0ff) << 8) | 
      (((long)buffer[2] & 0x0ff) << 16) | 
      (((long)buffer[3] & 0x0ff) << 24) | 
      (((long)buffer[4] & 0x0ff) << 32) | 
      (((long)buffer[5] & 0x0ff) << 40) | 
      (((long)buffer[6] & 0x0ff) << 48) | 
      (((long)buffer[7] & 0x0ff) << 56); 

    return Double.longBitsToDouble(bits); 
} 

Code objc

/* 
* Retrieve a double (64-bit) number from the stream. 
*/ 
- (double)getDouble 
{ 
    NSRange dblRange = NSMakeRange(0, 8); 
    char buffer[8]; 

    [stream getBytes:buffer length:8]; 
    [stream replaceBytesInRange:dblRange withBytes:NULL length:0]; 

    long long bits = 
    ((long long)buffer[0] & 0x0ff) | 
    (((long long)buffer[1] & 0x0ff) << 8) | 
    (((long long)buffer[2] & 0x0ff) << 16) | 
    (((long long)buffer[3] & 0x0ff) << 24) | 
    (((long long)buffer[4] & 0x0ff) << 32) | 
    (((long long)buffer[5] & 0x0ff) << 40) | 
    (((long long)buffer[6] & 0x0ff) << 48) | 
    (((long long)buffer[7] & 0x0ff) << 56); 

    NSNumber *tempNum = [NSNumber numberWithLongLong:bits]; 
    NSLog(@"\n***********\nsizeof long long %d \n tempNum: %@\nbits %lld",sizeof(long long), tempNum, bits); 
    return [tempNum doubleValue]; 
} 

le résultat de NSLog est


sizeof long long 8 tempNum: -4616134021117358511 bits de -4616134021117358511

le nombre doit être: -1.Le problème est que j'essaie de convertir Java en objC dans la fonction getDouble. Mon middleware prend en compte les problèmes endian. La solution est simple si la cible est peu endian

- (double)getDouble 

NSRange dblRange = NSMakeRange(0, 8); 
double swapped; 

[stream getBytes:&swapped length:8]; 
[stream replaceBytesInRange:dblRange withBytes:NULL length:0]; 



return swapped; 

Merci à tous pour l'entrée - ont obtenu beaucoup d'expérience et un peu de compréhension de cet exercice.

Répondre

3

Un double et un long long ne sont pas la même chose. Un long représente un entier, qui n'a pas de partie fractionnaire, et un double représente un nombre à virgule flottante, qui a une partie fractionnaire. Ces deux types ont des façons complètement différentes de représenter leurs valeurs dans la mémoire. C'est-à-dire, si vous deviez regarder longuement les bits représentant le nombre 4000 et les comparer aux bits pour un double représentant le nombre 4000, ils seraient différents. Comme le note Wevah, la première étape consiste à utiliser le bon type double et le bon formateur% f dans votre appel à NSLog().

J'ajouterais, cependant, que vous devez également faire attention à obtenir vos octets dans l'ordre natif pour la machine sur laquelle votre code C s'exécute. Pour une description détaillée de ce dont je parle, voir http://en.wikipedia.org/wiki/Endianness La version courte est que différents processeurs peuvent représenter des nombres de différentes manières en mémoire, et vous devez vous assurer dans votre code qu'une fois que vous avez une pile d'octets du réseau, vous placez les octets dans le bon ordre pour votre processeur avant de tenter de l'interpréter comme un nombre.

Heureusement, cela est un problème résolu, et est facilement représenté en utilisant la fonction de CoreFoundation CFConvertFloat64SwappedToHost():

[stream getBytes:buffer length:8]; 
[stream replaceBytesInRange:dblRange withBytes:NULL length:0]; 

double myDouble = CFConvertFloat64SwappedToHost(*((double*)buffer)); 
NSNumber *tempNum = [NSNumber numberWithDouble:myDouble]; 
NSLog(@"\n***********\nsizeof double %d \n tempNum: %@\nbits %f",sizeof(double), tempNum, myDouble); 
return [tempNum doubleValue]; 
+0

Je vais vous donner celui-ci. :) – Wevah

+0

Eh bien, l'ordre des octets est juste une situation difficile à essayer et à déboguer de l'autre côté de la situation. :) – Ryan

+0

double myDouble = CFConvertFloat64SwappedToHost (tampon (double)); xCode indique la valeur du pointeur utilisée lorsqu'un point flottant était attendu –

0

Vous souhaitez probablement le convertir en double (probablement/probablement via une union, voir le commentaire de Jonathan) et utiliser le spécificateur %f.

+1

Pas un casting droit, comme cela vient lui faire -4616134021117358511 comme un double. Il veut réinterpréter les bits; la façon habituelle de le faire est de vider le 'long long' dans un' union' avec un 'double', puis de lire le' double'. Apple a aussi son 'CFConvertDoubleSwappedToHost()' mais il est destiné à traiter la conversion opaque, donc ce n'est pas exactement la bonne chose pour ce cas. –

+0

@Jonathan: Vous avez raison à propos de la conversion; éditer mon post (et +1). – Wevah