5
votes

Vecteur de structure personnalisée dans PyO3

Je suis nouveau dans Rust et PyO3 (venant de Python) donc cela pourrait être évident pour les personnes plus expérimentées.

J'ai déclaré une structure pyclass dans PyO3.

#[pyfunction]
fn from_blocks(block_list: Vec<Block>) -> Vec<i32>

Ensuite, j'utilise Block dans une fonction rust qui prend un vecteur de Block et génère un vecteur de int (signature ci-dessous)

#[pyfunction]
fn to_blocks(list: Vec<i32>) -> Vec<Block>


1 commentaires

Désolé de confondre tout le monde. @Caio a intuitivement compris que la fonction incriminée a la signature inverse. J'ai mis à jour la question en conséquence.


3 Réponses :


1
votes

Il semble que l'attribut pyfunction génère du code qui nécessite que le type de retour implémente le trait FromPyObject . Bien qu'il existe une implémentation générale de FromPyObject for Vec où T: FromPyObject , il semble que le code généré pour l'attribut pyclass n'inclut pas une implémentation de FromPyObject pour votre type de Bloquer .

Étant donné que je ne suis pas familier avec PyO3 à part les quelques minutes où je viens de regarder sa documentation API pour valider cette réponse, je ne suis pas sûr de la meilleure façon d'obtenir une implémentation FromPyObject - peut-être il y a un dérivé pour cela?


0 commentaires

4
votes

FromPyObject est destiné à être utilisé par des types qui peuvent être extraits du monde Python. C'est pourquoi je pense que vous essayiez d'écrire fn to_blocks (list: Vec ) -> Vec au lieu de fn to_blocks (list: Vec ) - > Vec . Si tel est le cas, passons à la chaîne d'implémentation.

FromPyObject a une implémentation par défaut pour tout & T qui implémente PyTryFrom et PyTryFrom a une implémentation par défaut pour tout T qui implémente PyTypeInfo . [pyclass] implémente PyObjectAlloc ou PyObjectWithFreeList selon le impl_class méthode et les deux traits ont le trait PyTypeInfo lié. Par conséquent, votre classe / structure fonctionnera très bien avec des références, par exemple:

#[pyfunction]
fn to_blocks(list: Vec<&Block>) -> Vec<i32>

Vous pouvez voir dans la documentation officielle cette explication de manière résumée.

FromPyObject est implémenté par différents types qui peuvent être extraits depuis un objet Python référence .


8 commentaires

Pourquoi une fonction nommée to_blocks prendrait-elle un vecteur de blocs en entrée et retournerait-elle un vecteur d'entiers?


Malgré le nom, fn to_blocks (list: Vec ) -> Vec compile sans problème et même s'il ne compile pas, l'erreur serait différente.


Je ne comprends pas votre commentaire. S'il se compile sans problème, pourquoi le réparer? Dans tous les cas, cela n'a aucun sens de suggérer d'échanger les entrées et les sorties de la fonction car cela ne donnerait pas à OP ce dont il a besoin.


L'erreur de compilation qu'il a donnée dans cette question est simplement liée au fait que les dérivations personnalisées ne sont pas suffisantes pour permettre à un type appartenant à un local d'être utilisé dans un paramètre de fonction. C'est pourquoi j'ai suggéré qu'il aurait pu écrire le mauvais code et si tel était le cas, les mesures ci-dessus de cette réponse seraient nécessaires . Si je n'étais pas assez clair, je peux modifier mon message de manière appropriée.


Êtes-vous en train de dire que le code qu'il a réellement compilé n'est pas le code indiqué dans la question? Si tel est le cas, dire "votre code devrait être" est déroutant car il semble que vous suggérez que cela résoudrait le problème.


@interjay, @caio s'excuse pour la confusion. Je pense que @caio a compris que depuis que j'ai un fn to_blocks , alors il y a un contraire qui fait l'inverse et c'est ce qui donne l'erreur.


Merci kentwait. @interjay a fait des déclarations importantes qui sont maintenant corrigées.


La documentation pyo3 est encore mince à ce sujet. Il a fallu beaucoup de recherches sur Google pour trouver ce fil. Merci



0
votes

Quelle version de PyO3 utilisez-vous? Votre code fonctionne pour moi sur 0.5.3 et 0.6.0-alpha.1 .

Pour cette raison, je ne peux pas tester cela, mais je suppose dont vous avez besoin pour renvoyer un PyResult:

#[pyfunction]
fn to_blocks(list: Vec<i32>) -> PyResult<Vec<Block>>


5 commentaires

# [pyclass] implémente IntoPyObject / ToPyObject pour Block , c'est pourquoi cela fonctionne. Le code OP devrait probablement être fn to_blocks (list: Vec ) -> Vec .


@Caio Je suis confus - puisque le code d'OP fonctionne, pourquoi devrait-il être autre chose?


Parce que le message d'erreur qu'il a donné est le même message d'erreur que celui que l'on obtient lorsque Block est utilisé comme paramètre d'entrée. Pour être sûr, je pense qu'il vaut mieux attendre sa réponse à ce sujet.


@Caio vous avez raison, j'ai retracé l'erreur jusqu'à la mauvaise fonction. L'erreur provient de fn from_blocks (block_list: Vec ) -> Vec


@kentwait Merci =)