Pregunta

Así que estoy portando xxhash desde el uso de la CGO para ir al nativo de 9p C, sin embargo, 'M Corriendo en un problema bastante raro.

La función hash funciona perfectamente si se llama como una función de CGO, sin embargo, si intento usar la versión "nativa", devuelve el hash incorrecto.

Sé lo suficiente C para que funcione, pero antes de informar sobre el problema, quiero asegurarme de que no esté haciendo nada malo.

GIST

xxhash.go:

//#include "xxhash_9p.c"
//import "C" //uncomment this and comment the next line for the cgo version
func XXH32_test(in unsafe.Pointer, l uint32, seed uint32) uint32


func GoXXH32(in []byte, seed uint32) (h uint32) {
    //omitted, full version in the gist above
}

func main() {
    b := []byte("ABCDEFGLAALSDLSD:LSDL:DL:DL:SDL:SL:DSL:DL:DSL:DL:{W{EOQWExzghp[[")
    fmt.Println(XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0)) //uncomment this and comment the next line for the cgo version
    //fmt.Println(C.XXH32_test(unsafe.Pointer(&b[0]), C.uint(len(b)), 0))
    fmt.Println(GoXXH32(b, 0)) //this is tested against the C implementation and it's the right hash.
}

xxhash_9p.c:

#define PRIME32_1   2654435761U
#define PRIME32_2   2246822519U
#define PRIME32_3   3266489917U
#define PRIME32_4    668265263U
#define PRIME32_5    374761393U

#define U32 unsigned int
typedef struct _U32_S { U32 v; } U32_S;
#define A32(x) (((U32_S *)(x))->v)

U32 ·XXH32_test(const void* input, U32 len, U32 seed) {
//static U32 XXH32_test(const void* input, U32 len, U32 seed) {
    const char* p = (const char*)input;
    const char* bEnd = p + len;
    U32 h32;

    #define XXH_get32bits(p) A32(p)
    #define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))

    if (len>=16) {
        const char* const limit = bEnd - 16;
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
        U32 v2 = seed + PRIME32_2;
        U32 v3 = seed + 0;
        U32 v4 = seed - PRIME32_1;
        do
        {
            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
        } while (p<=limit);

        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
    }
    else
    {
        h32  = seed + PRIME32_5;
    }

    h32 += (unsigned long) len;
    while (p<=bEnd-4) {
        h32 += XXH_get32bits(p) * PRIME32_3;
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
        p+=4;
    }

    while (p<bEnd) {
        h32 += (*p) * PRIME32_5;
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
        p++;
    }

    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;
    return h32;
}

Ejecutar:

$ go build && ./nocgo #9p native
134316512
981225178
$ go build && ./nocgo #cgo
981225178
981225178

tl; dr:

Una función C devuelve el valor incorrecto cuando se usa a través de GO's 6c, la misma función CAC exacta devuelve el valor correcto cuando se llama a través de la CGO.

// Editar

Recibí una respuesta en la problema , no es Voy a ser arreglado y el Playchain de 9P se va al finalmente.

de mi ... @ golang.org :

El compilador C eventualmente desaparecerá. Plan para eso, así que no confíes en eso.

NOTA El compilador del plan 9 C no es compatible con ANSI, y no estamos va a arreglar errores en ella (porque controlamos tanto el compilador como su Entrada, simplemente solucionaremos sus errores).

¿Fue útil?

Solución

Después de cavar, cambiando la firma de la función de

U32 ·XXH32_test(const void* input, U32 len, U32 seed)

a

void ·XXH32_test(const unsigned char* input, U32 len, U32 seed, U32 *ret)

y llamándolo así:

var u uint32
XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0, &u)

devuelve el hash correcto.

Todavía no estoy seguro de lo que está sucediendo, es debería trabajar cómo fue originalmente, pero supongo que el tiempo de ejecución está haciendo una magia detrás de las escenas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top