Question

J'essaye de me connecter à MySQL à partir du code de rouille. J'ai essayé ces étapes.

    1. J'ai écrit le code C en utilisant mysql.h, et commande ci-dessous.
    
     $ 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. J'ai écrit du code rouille, qui appelle libmysqlrust.so.

Mais je ne pouvais pas trouver un moyen d'utiliser la structure de type C "MYSQL", "MYSQL_RES", "MYSQL_ROW". Veuillez me montrer comment utiliser la structure de type C de Rust Code.

Était-ce utile?

La solution

Il n'y a pas encore de moyen de créer automatiquement des définitions de type de rouille à partir de C. Dans ces situations, il existe plusieurs façons de procéder. Ne connaissant pas l'API MySQL, je ne peux pas dire exactement ce que vous devez faire, mais voici quelques options.

1) Traitez-les entièrement comme des pointeurs opaques.

C'est la meilleure situation à se trouver, et dépend de l'API C prenant toujours la structure en tant que pointeur, ayant ses propres fonctions de constructeur et de destructeur, et de fournir des fonctions d'accessoires pour tout ce dont vous avez besoin pour accéder à l'intérieur de la structure. Dans ces cas, vous ne définissez que type MYSQL = ctypes::void et ne l'utilise que comme un pointeur dangereux *MYSQL. Parfois, le chemin le plus simple est d'écrire vos propres emballages C pour combler les lacunes et rendre ce scénario possible.

Les scénarios restants impliquent tous de redéfinir une structure de données de rouille avec la même structure que la structure C. Rust essaie de disposer ses structures de données d'une manière compatible avec C (bien que ne réussisse pas encore toujours), il est donc souvent possible de créer un enregistrement de rouille ou une énumération avec la taille, l'alignement et la disposition de la structure C vous se soucier de. Vous voudrez vous assurer d'utiliser les types dans core::ctypes, tels qu'ils sont définis pour correspondre à divers types C communs.

Notez que le ctypes Le module disparaîtra bientôt en faveur d'un module de compatibilité LIBC plus complet.

2) Définissez un enregistrement de rouille partiellement correct.

Si l'API fournit des constructeurs et des destructeurs, mais que vous avez toujours besoin d'accéder à certains champs de la structure, vous pouvez définir juste assez de la structure pour obtenir les champs qui vous tiennent à cœur, sans tenir compte des choses comme la taille et l'alignement corrects. par exemple type MSQL = { filler1: ctypes::int, ..., connector_fd: *ctypes::char }. Vous pouvez arrêter de définir la structure au dernier champ qui vous tient à cœur car vous avez une fonction C pour l'allouer sur le tas avec la taille et l'alignement corrects. Dans le code rouillé, vous vous y référez toujours avec un pointeur dangereux: let mysql: *MYSQL = mysqlrust::create_mysql();

3) Définissez un enregistrement de rouille qui est la taille et l'alignement corrects, sans se soucier du contenu.

Si vous n'avez pas de fonctions de constructeur / destructeur, ou si vous avez besoin de stocker la structure sur la pile, mais que vous avez autrement des fonctions d'accessoires pour manipuler le contenu de la structure, vous devez définir un enregistrement de rouille avec la taille et l'alignement corrects. Pour ce faire, ajoutez simplement des champs de type uint (qui est toujours de la taille d'un pointeur) ou des tuples de uint, jusqu'à ce que les deux C sizeof et core::sys::size_of d'accord sur la taille. Tampon avec u8s Si la taille n'est pas un multiple de la taille du pointeur. Obtenir le bon alignement est un processus plus mystique, mais en utilisant uint champs, vous vous retrouverez généralement avec un alignement utilisable (peut-être - je n'ai vraiment aucune idée de la précision de cette déclaration).

Je recommanderais d'ajouter des tests à la santé mentale que Rust et C s'accordent sur la taille afin de se prémunir contre la rupture future.

3) Redéfinissez en fait l'intégralité de la structure C.

C'est une situation assez désastreuse pour les grandes structures, et c'est possible en théorie, mais je ne pense pas que quiconque l'a fait pour une structure aussi grande que MYSQL. Je l'éviterais si vous le pouvez. Finalement, il y aura un outil basé sur Clang pour le faire automatiquement.

Voici quelques exemples d'interopérations avec les structures C:

https://github.com/jdm/rust-socket/blob/master/socket.rs - Cela redéfinit diverses structures de socket, ajoutant des espaces réservés pour les champs qui ne se soucient pas. Notez qu'il utilise u8 pour le rembourrage, mais je pense uint est plus susceptible de produire un alignement correct.

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

https://github.com/pcwalton/rust-pidermonkey - Celui-ci démontre l'interopération avec une API quelque peu complexe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top