Domanda

Sto cercando di connettermi a MySQL da Rust Code. Ho provato questi passaggi.

    1. Ho scritto il codice C usando mysql.h, e comanda di seguito.
    
     $ 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. Ho scritto Rust Code, che chiama libmysqlrust.so.

Ma non riuscivo a capire la strada per usare la struttura del tipo C "MYSQL", "MYSQL_RES", "MYSQL_ROW". Per favore, mostrami come utilizzare la struttura del tipo C dal codice ruggine.

È stato utile?

Soluzione

Non esiste ancora alcun modo per creare automaticamente definizioni di tipo ruggine dalle strutture C. In queste situazioni ci sono alcuni modi per procedere. Non conoscendo l'API MySQL, non posso dire esattamente cosa dovresti fare, ma ecco alcune opzioni.

1) Trattali interamente come puntatori opachi.

Questa è la situazione migliore in cui trovarsi e dipende dall'API C che prende sempre la struttura come puntatore, avendo le sue funzioni di costruttore e distruttore e fornendo funzioni di accessori per tutto ciò che è necessario accedere all'interno della struttura. In questi casi si definisce type MYSQL = ctypes::void e usarlo solo sempre come un puntatore non sicuro *MYSQL. A volte il percorso più semplice è scrivere i tuoi involucri C per colmare le lacune e rendere possibile questo scenario.

Gli scenari rimanenti comportano tutti la ridefinizione di una struttura di dati ruggine con la stessa struttura della struttura C. Rust cerca di disporre le sue strutture di dati in un modo compatibile con C (sebbene non sempre abbia ancora successo), quindi è spesso possibile creare un record di ruggine o enum con le dimensioni, l'allineamento e il layout della struct C Care. Vorrai assicurarti di utilizzare i tipi in core::ctypes, come sono definiti per abbinare vari tipi C comuni.

Nota che il ctypes Il modulo andrà via presto a favore di un modulo di compatibilità LIBC più completo.

2) Definire un record di ruggine parzialmente corretto.

Se l'API fornisce costruttori e distruttori, ma è ancora necessario accedere ad alcuni campi della struttura, puoi definire la sufficiente struttura per ottenere nei campi a cui tieni, ignorando le cose come le dimensioni e l'allineamento corretti. per esempio type MSQL = { filler1: ctypes::int, ..., connector_fd: *ctypes::char }. Puoi smettere di definire la struttura nell'ultimo campo a cui tieni poiché hai una funzione C per allocarla sul mucchio con le dimensioni e l'allineamento corretti. Nel codice ruggine ti riferisci sempre ad esso con un puntatore non sicuro: let mysql: *MYSQL = mysqlrust::create_mysql();

3) Definire un record di ruggine che è la dimensione e l'allineamento corretti, senza prendersi cura del contenuto.

Se non si dispone di funzioni di costruttore/distruttore o devi archiviare la struttura sullo stack, ma altrimenti si dispone di funzioni di accessori per manipolare il contenuto della struttura, è necessario definire un record di ruggine con le dimensioni e l'allineamento corretti. Per fare questo, basta aggiungere campi di tipo uint (che è sempre di dimensioni puntarie) o tuple di uint, fino a entrambe le C sizeof e core::sys::size_of d'accordo sulle dimensioni. Pad con u8S Se la dimensione non è un multiplo della dimensione del puntatore. Ottenere il giusto allineamento è un processo più mistico, ma usando uint Fields generalmente finirai con un allineamento utilizzabile (forse - non ho davvero idea di quanto sia accurata tale affermazione).

Consiglierei di aggiungere test al controllo di sanità mentale che Rust e C siano d'accordo sulle dimensioni per proteggersi dalle future rotture.

3) Ridefinire effettivamente l'intera struttura C.

Questa è una situazione piuttosto terribile per le strutture di grandi dimensioni, ed è possibile in teoria, ma non credo che nessuno lo abbia fatto per una struttura grande come MYSQL. Lo eviterei se puoi. Alla fine ci sarà uno strumento basato su Clang per farlo automaticamente.

Ecco alcuni esempi di interrogarsi con le strutture C:

https://github.com/jdm/Rust-Socket/blob/master/socket.rs - Ciò ridefinisce varie strutture di socket, aggiungendo segnaposto per i campi a cui non importa. Nota che utilizza u8 per l'imbottitura, ma penso uint è più probabile produrre un corretto allineamento.

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

https://github.com/pcwalton/rust-spidermonkey - Questo dimostra interrogare con un'API un po 'complessa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top