es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo hacer que un void** sea un parámetro de una biblioteca en C?

Estoy tratando de llamar a una biblioteca en C desde GO utilizando cgo.

La biblioteca en C tiene la siguiente función:

int receive(void** data);

// Yo lo llamaría así:
void* myptr; // myptr=null
int nbBytes = receive(&myptr);
if (nbBytes==0) { return }
// myptr ahora tiene la dirección de un búfer válido que contiene nbBytes bytes.

// Luego, lo puedo convertir a char* para acceder a los datos, que pueden ser cualquier cosa. Ejemplo:
printf(“%d”, (char*)myptr);

¿Cómo puedo llamar a esta función receive() desde GO? GO no asigna memoria, la dirección de memoria se devuelve a través de myptr y se accede directamente desde ella.

  • receive() es una función “sin copia” y escribe la dirección real de los datos en myptr. Los datos se acceden utilizando (char)myptr.
  • Podemos asumir que receive() asigna y libera el búfer, está oculto para el usuario de la librería.

Idealmente, me gustaría leer los datos a través de []byte en Go.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para llamar a la función receive() en C desde Go usando cgo, puedes hacer lo siguiente:

    1. Declara el prototipo de la función C en tu archivo de Go:
    // #include <stdlib.h>
    // int receive(void** data);
    import "C"
    
    1. Define una función envolvente en Go alrededor de la función receive() que retorna un []byte:
    func Receive() []byte {
        var ptr unsafe.Pointer
        nbBytes := C.receive(&ptr)
        defer C.free(ptr) // liberar memoria después de su uso
        if nbBytes == 0 {
            return nil
        }
        // copiar los datos desde el buffer C a un []byte en Go
        data := C.GoBytes(ptr, C.int(nbBytes))
        return data
    }
    

    La función C.receive() retorna la cantidad de bytes recibidos y también escribe la dirección de memoria en ptr. Luego utilizamos C.GoBytes() para convertir el buffer C a un []byte en Go. La declaración defer asegura que la memoria se libere después de que la función retorne.

    1. Usa la función envolvente en tu código de Go:
    data := Receive()
    if data == nil {
        return
    }
    // accede a los datos según sea necesario, por ejemplo, data[0]
    

    Esto te permitirá llamar a la función receive() en C desde Go y acceder a los datos como un []byte.</stdlib.h>

Comments are closed.