2009-06-28 59 views
3

我想發送一個Java UUID到C++,它將作爲一個GUID使用,然後將其發送回來並將其視爲一個UUID, m希望只發送16個字節。發送一個Java UUID到C++作爲字節並返回到TCP

任何建議在一個簡單的方法來做到這一點?我有一個複雜的方式,從Java發送到C++,在那裏我要求UUID獲取最少和最重要的位,將它寫入ByteBuffer,然後以字節讀出。

這是我得到2個多頭出UUID的,將它們發送到C++的愚蠢,複雜的方式:

的Java

public static byte[] asByteArray(UUID uuid) 
{ 
    long msb = uuid.getMostSignificantBits(); 
    long lsb = uuid.getLeastSignificantBits(); 
    byte[] buffer = new byte[16]; 

    for (int i = 0; i < 8; i++) { 
      buffer[i] = (byte) (msb >>> 8 * (7 - i)); 
    } 
    for (int i = 8; i < 16; i++) { 
      buffer[i] = (byte) (lsb >>> 8 * (7 - i)); 
    } 

    return buffer; 

} 




    byte[] bytesOriginal = asByteArray(uuid); 
    byte[] bytes = new byte[16]; 

    // Reverse the first 4 bytes 
    bytes[0] = bytesOriginal[3]; 
    bytes[1] = bytesOriginal[2]; 
    bytes[2] = bytesOriginal[1]; 
    bytes[3] = bytesOriginal[0]; 
    // Reverse 6th and 7th 
    bytes[4] = bytesOriginal[5]; 
    bytes[5] = bytesOriginal[4]; 
    // Reverse 8th and 9th 
    bytes[6] = bytesOriginal[7]; 
    bytes[7] = bytesOriginal[6];         
    // Copy the rest straight up   
    for (int i = 8; i < 16; i++) 
    { 
     bytes[i] = bytesOriginal[i]; 
    }  

    // Use a ByteBuffer to switch our ENDIAN-ness 
    java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(16); 
    buffer.order(java.nio.ByteOrder.BIG_ENDIAN); 
    buffer.put(bytes); 
    buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN); 
    buffer.position(0); 

    UUIDComponents x = new UUIDComponents(); 

    x.id1 = buffer.getLong(); 
    x.id2 = buffer.getLong(); 

C++

google::protobuf::int64 id1 = id.id1(); 
    google::protobuf::int64 id2 = id.id2(); 

    char* pGuid = (char*) &guid; 
    char* pGuidLast8Bytes = pGuid + 8; 
    memcpy(pGuid, &id1, 8); 
    memcpy(pGuidLast8Bytes, &id2, 8); 

這工作,但似乎方式太複雜,我還不能在另一個方向上工作。

(我使用谷歌協議緩衝區的兩個多頭來回發送)

  • 亞歷

回答

2

我得到了一些工作。

而不用通過發送它作爲兩個多頭的,我把它整個的字節,這裏是Java代碼:

public static UUID fromBytes(ByteString byteString) 
{ 
    byte[] bytesOriginal = byteString.toByteArray(); 
    byte[] bytes = new byte[16]; 

    // Reverse the first 4 bytes 
    bytes[0] = bytesOriginal[3]; 
    bytes[1] = bytesOriginal[2]; 
    bytes[2] = bytesOriginal[1]; 
    bytes[3] = bytesOriginal[0]; 
    // Reverse 6th and 7th 
    bytes[4] = bytesOriginal[5]; 
    bytes[5] = bytesOriginal[4]; 
    // Reverse 8th and 9th 
    bytes[6] = bytesOriginal[7]; 
    bytes[7] = bytesOriginal[6];         
    // Copy the rest straight up   
    for (int i = 8; i < 16; i++) 
    { 
     bytes[i] = bytesOriginal[i]; 
    }  

    return toUUID(bytes); 
} 

public static ByteString toBytes(UUID uuid) 
{ 
    byte[] bytesOriginal = asByteArray(uuid); 
    byte[] bytes = new byte[16]; 

    // Reverse the first 4 bytes 
    bytes[0] = bytesOriginal[3]; 
    bytes[1] = bytesOriginal[2]; 
    bytes[2] = bytesOriginal[1]; 
    bytes[3] = bytesOriginal[0]; 
    // Reverse 6th and 7th 
    bytes[4] = bytesOriginal[5]; 
    bytes[5] = bytesOriginal[4]; 
    // Reverse 8th and 9th 
    bytes[6] = bytesOriginal[7]; 
    bytes[7] = bytesOriginal[6];         
    // Copy the rest straight up   
    for (int i = 8; i < 16; i++) 
    { 
     bytes[i] = bytesOriginal[i]; 
    }  

    return ByteString.copyFrom(bytes); 
} 


private static byte[] asByteArray(UUID uuid) 
{ 
    long msb = uuid.getMostSignificantBits(); 
    long lsb = uuid.getLeastSignificantBits(); 
    byte[] buffer = new byte[16]; 

    for (int i = 0; i < 8; i++) { 
      buffer[i] = (byte) (msb >>> 8 * (7 - i)); 
    } 
    for (int i = 8; i < 16; i++) { 
      buffer[i] = (byte) (lsb >>> 8 * (7 - i)); 
    } 

    return buffer; 

} 

private static UUID toUUID(byte[] byteArray) { 

    long msb = 0; 
    long lsb = 0; 
    for (int i = 0; i < 8; i++) 
      msb = (msb << 8) | (byteArray[i] & 0xff); 
    for (int i = 8; i < 16; i++) 
      lsb = (lsb << 8) | (byteArray[i] & 0xff); 
    UUID result = new UUID(msb, lsb); 

    return result; 
} 

這樣做,這樣,該字節可以直線上升的C++端使用。我認爲,在結束時可以完成字節順序的切換。

C++

memcpy(&guid, data, 16); 
1

這可能是最容易使用getMostSignificantBitsgetLeastSignificant位獲得long值,併發送那些。同樣,您可以使用適當的構造函數從這兩個longs中重建UUID。

這是一個恥辱,沒有一個toByteArray /fromByteArray對方法:(

+0

感謝Jon的迴應。所以我嘗試了這種方式,並且將長整型值放回到另一端的GUID中並不容易:) 我的工作方式是單向的,但不是其他方式。我會爲我的問題添加一些代碼。 – 2009-06-28 18:26:15

+0

您不應該在Java端切換長整型的字節順序。你可能不得不在C++端。 – 2009-06-28 18:46:52

0

也許你可以解釋爲什麼你不只是做。

UUID uuid = 
x.id1 = uuid.getMostSignificantBits(); 
x.id2 = uuid.getLeastSignificantBits(); 

PS當我讀到@喬恩飛碟雙向的帖子再次,我認爲這是非常相同的建議;)

1

你目前的方式是好的,這樣做沒有錯。 另一個方法是喲只是與uuid的字符串表示形式進行通信,發送字符串,用C++解析它。

順便說一下,字節沒有字節數,除非你將字節/字符數組或類似字符轉換爲整數類型,否則只需通過按適當順序返回字節來確定字節數。

1

這是我做的一個C++ GUID轉換爲一個Java UUID。在C++端,GUID結構只是轉換爲字節。然後轉換到C++就可以沿着同樣的路線前進。

public static UUID cppGuidBytesToUuid(byte[] cppGuid) { 
    ByteBuffer b = ByteBuffer.wrap(cppGuid); 
    b.order(ByteOrder.LITTLE_ENDIAN); 
    java.nio.ByteBuffer out = java.nio.ByteBuffer.allocate(16); 
    out.order(ByteOrder.BIG_ENDIAN); 
    out.putInt(b.getInt()); 
    out.putShort(b.getShort()); 
    out.putShort(b.getShort()); 
    out.put(b); 
    out.position(0); 
    return new UUID(out.getLong(), out.getLong()); 
} 


// Here is the JNI code ;-) 
jbyteArray GUID2ByteArray(JNIEnv *env,GUID* guid) 
{ 
    if (guid == NULL) 
    return NULL; 
    jbyteArray jGUID = env->NewByteArray(sizeof(GUID)); 
    if (jGUID == NULL) 
    return NULL; 
    env->SetByteArrayRegion(jGUID,0,sizeof(GUID),(signed char*)(guid)); 
    if (env->ExceptionOccurred() != NULL) 
    return NULL; 
    return jGUID; 
} 
相關問題