2012-02-26 24 views
11

Estoy tratando de conectarme a mysql desde el código de óxido. Probé estos pasos.Quiero llamar a la biblioteca C "mysql.h" del lenguaje Rust

    1. Escribí el código c usando mysql.h, y el comando a continuación.
    
    $ gcc -shared mysqlrust.c -o libmysqlrust.so $(mysql_config --cflags) $(mysql_config --libs) $(mysql_config --cflags) 
    $ cp libmysqlrust.so /usr/local/lib/rustc/i686-unknown-linux-gnu/lib/ 
    
    2. Escribí el código Rust, que llama al libmysqlrust.so.

Pero no pude averiguar manera de utilizar estructura de tipo C "MYSQL", "MYSQL_RES", "MYSQL_ROW". Por favor, muéstrame cómo usar la estructura tipo c del código de óxido.

+2

Veamos el código que ha escrito y los mensajes de error exactos – Mark

+1

http://doc.rust-lang.org/doc/tutorial.html#passing-structures –

Respuesta

17

Aún no hay forma de crear automáticamente definiciones de tipo Rust a partir de estructuras C. En estas situaciones, hay algunas maneras de proceder. Al no conocer la API de MySQL, no puedo decir exactamente lo que debe hacer, pero aquí hay algunas opciones.

1) Trátelos por completo como punteros opacos.

Esta es la mejor situación para estar, y depende de que la API C siempre tome la estructura como puntero, tenga sus propias funciones de constructor y destructor y proporcione funciones de acceso para lo que necesite acceder dentro de la estructura. En estos casos, solo define type MYSQL = ctypes::void y solo lo usa como un puntero inseguro *MYSQL. Algunas veces, la ruta más fácil es escribir sus propios envoltorios de C para llenar los vacíos y hacer posible este escenario.

El resto de los escenarios implican la redefinición de una estructura de datos Rust con la misma estructura que la estructura C. Rust intenta diseñar sus estructuras de datos de una manera que sea compatible con C (aunque no siempre lo logra), por lo que a menudo es posible crear un registro o enumeración de Rust con el tamaño, la alineación y el diseño de la estructura C preocuparse. Deberá asegurarse de utilizar los tipos en core::ctypes, ya que están definidos para coincidir con varios tipos de C comunes.

Tenga en cuenta que el módulo ctypes desaparecerá pronto a favor de un módulo de compatibilidad de libc más completo.

2) Defina un registro de Rust parcialmente correcto.

Si la API proporciona constructores y destructores, pero aún necesita acceso a algunos campos de la estructura, puede definir lo suficiente de la estructura para llegar a los campos que le interesan, sin tener en cuenta el tamaño y la alineación correctos . p.ej. type MSQL = { filler1: ctypes::int, ..., connector_fd: *ctypes::char }. Puede dejar de definir la estructura en el último campo que le interesa ya que tiene una función C para asignarla en el montón con el tamaño y la alineación correctos. En el código Rust siempre se refiere a él con un puntero inseguro: let mysql: *MYSQL = mysqlrust::create_mysql();

3) Defina un registro de óxido que tenga el tamaño y la alineación correctos, sin preocuparse por el contenido.

Si no tiene funciones de constructor/destructor, o necesita almacenar la estructura en la pila, pero tiene funciones de acceso para manipular el contenido de la estructura, entonces necesita definir un registro de Rust con la correcta tamaño y alineación Para hacer esto, simplemente agregue los campos del tipo uint (que siempre es del tamaño de un puntero) o tuplas de uint, hasta que ambos C sizeof y core::sys::size_of acuerden el tamaño. Rellene con u8 s si el tamaño no es un múltiplo del tamaño del puntero. Obtener la alineación correcta es un proceso más místico, pero al usar los campos uint generalmente terminará con una alineación utilizable (tal vez, realmente no tengo idea de qué tan precisa es esa afirmación).

Recomendaría agregar pruebas a la comprobación de cordura que Rust y C acuerden sobre el tamaño para evitar futuras roturas.

3) En realidad redefinir toda la estructura C.

Esta es una situación bastante grave para grandes estructuras, y es posible en teoría, pero no creo que nadie lo haya hecho para una estructura tan grande como MYSQL. Lo evitaría si puedes. Eventualmente habrá una herramienta basada en clang para hacer esto automáticamente.

Éstos son algunos ejemplos de interoperabilidad con estructuras C:

https://github.com/jdm/rust-socket/blob/master/socket.rs - Este redefine diversas estructuras de socket, la adición de marcadores de posición para los campos que no le interesan en. Tenga en cuenta que utiliza u8 para el relleno, pero creo que uint es más probable que produzca una alineación correcta.

https://github.com/erickt/rust-zmq/blob/master/zmq.rs

https://github.com/pcwalton/rust-spidermonkey - Éste demuestra interoperabilidad con un API algo complejo.

+0

He redefinido estas estructuras en herrumbre y definí funciones. tipo MYSQL = ctypes :: void; tipo MYSQL_RES = ctypes :: void; tipo MYSQL_ROW = ctypes :: void; y tengo que proceder. Pero otro problema. No puedo convertir ** char a array of str. ¿Cómo debo resolverlo? Gracias. –

+0

Tendrá que usar un código no seguro para recorrer la matriz de cadenas C y convertirlas en un vector de cadenas de óxido. Algo así como https://gist.github.com/1928234 (no probado) – brson

+0

Lo tengo. He utilizado con éxito el código inseguro "str :: from_cstr". Muchas gracias. :) –