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>
3 Réponses :
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
, 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?
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
au lieu de fn to_blocks (list: 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 .
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
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
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>>
# [pyclass]
implémente IntoPyObject
/ ToPyObject
pour Block
, c'est pourquoi cela fonctionne. Le code OP devrait probablement être fn to_blocks (list: 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
@kentwait Merci =)
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.