Frage

Ich versuche, einen Java-UUID zu C ++ zu schicken, wo sie als GUID verwendet werden, es dann zurückschicken und sich als UUID sehen, und ich hoffe, dass es nur 16 Bytes über als senden.

Irgendwelche Vorschläge auf einfache Art und Weise, dies zu tun?

Ich habe einen komplizierten Weg kommt es zu tun, von Java nach C Senden ++, wo ich die UUID für seinen am wenigsten stellen und höchstwertigen Bits, schreiben diese in eine ByteBuffer, und es dann als Bytes ausgelesen werden.

Hier ist mein dummer komplizierter Weg, um 2 longs aus einer UUID, um sie zu C ++ zu senden:

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);

Dies funktioniert, aber scheint viel zu komplex, und ich kann noch nicht bekommen es in die andere Richtung zu arbeiten.

(Ich verwende Google Protokoll Puffer, um die zwei Long-Positionen hin und her zu senden)

  • Alex
War es hilfreich?

Lösung

Ich habe etwas arbeiten.

Statt es über zwei longs zu senden, ich habe es über als Bytes senden, hier ist der Java-Code:

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;
}

es auf diese Weise tun, kann der Bytes auf der Seite ++ C gerade nach oben verwendet werden. Ich nehme an dem Schalt um von der Reihenfolge des Bytes auf getan werden könnte, entweder Ende.

C ++

    memcpy(&guid, data, 16);

Andere Tipps

Es ist vielleicht am einfachsten getMostSignificantBits und getLeastSignificant Bits zu verwenden long Werte zu erhalten, und diejenigen zu senden. Ebenso können Sie die UUID aus diesen beiden Long-Positionen mit dem entsprechenden Konstruktor rekonstruieren.

Es ist schade, dass es keine toByteArray / fromByteArray Paar Methoden: (

Ihre aktuelle Art und Weise ist in Ordnung, nichts falsch daran, dass die Art und Weise zu tun. Ein weiterer approace ist yo nur mit der String-Darstellung des UUID kommunizieren, die Zeichenfolge senden, analysiert es in C ++.

Btw, Bytes nicht Endianess haben, es sei denn Sie ein Byte / char-Array oder ähnlich einem Integer-Typ sind Gießen, die Sie gerade die Endianess bestimmen, indem die Bytes wieder in der approprate Reihenfolge zugeordnet werden.

Hier ist, was ich tue, um einen C ++ GUID in einer Java-UUID zu konvertieren. Auf der C ++ Seite wird der GUID struct nur Bytes umgewandelt. Die Umwandlung in C ++ können dann gehen Sie einfach auf der gleichen Linie.

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;
}

Vielleicht könnten Sie erklären, warum man nicht einfach tun.

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

P. S. Wie ich @ Jon Skeet Post wieder zu lesen, ich denke, das viel der gleiche Rat ist. ;)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top