Coup de pouce.Python - Comment retourner par référence?
Je suis d'utilisation de Boost.Python pour créer des modules Python de classes C++. Et j'ai rencontré un problème avec les références.
Condider le cas suivant où j'ai une classe Foo avec surchargé obtenir des méthodes qui peuvent soit retour par valeur ou par référence.
Précisant que la déclaration de valeur doit être utilisée était facile une fois que j'ai typedefed une signature. Mais je pense qu'il devrait être possible de retourner une référence aussi bien à l'aide d'un return_value_policy
. Cependant, en utilisant ce qui me semblait approprié (doc); return_value_policy<reference_existing_object>
n'a pas l'air de fonctionner.
Ai-je mal compris ce qu'il fait?
struct Foo {
Foo(float x) { _x = x; }
float& get() { return _x; }
float get() const { return _x; }
private:
float _x;
};
//Wrapper code
BOOST_PYTHON_MODULE(my_module)
{
using namespace boost::python;
typedef float (Foo::*get_by_value)() const;
typedef float& (Foo::*get_by_ref)();
class_<Foo>("Foo", init<float>())
.def("get", get_by_value(&Foo::get))
.def("get_ref", get_by_ref(&Foo::get),
return_value_policy<reference_existing_object>())//Doesn't work
;
}
Note: je sais que ça pourrait être dangereux pour faire référence à un objet existant sans vie de gestion de temps.
Mise à jour:
On dirait qu'il travaille pour les objets mais pas les types de données de base.
Prenez cet exemple révisé:
struct Foo {
Foo(float x) { _x = x; }
float& get() { return _x; }
float get() const { return _x; }
void set( float f ){ _x = f;}
Foo& self(){return *this;}
private:
float _x;
};
//Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
typedef float (Foo::*get_by_value)() const;
class_<Foo>("Foo", init<float>())
.def("get", get_by_value(&Foo::get))
.def("get_self", &Foo::self,
return_value_policy<reference_existing_object>())
.def("set", &Foo::set);
;
}
Qui, dans un essai donné le résultat attendu:
>>> foo1 = Foo(123)
>>> foo1.get()
123.0
>>> foo2 = foo1.get_self()
>>> foo2.set(1)
>>> foo1.get()
1.0
>>> id(foo1) == id(foo2)
False
OriginalL'auteur mandrake | 2009-10-15
Vous devez vous connecter pour publier un commentaire.
En Python, il y a la notion de immuable types. Immuable type ne peuvent pas avoir la valeur est modifiée. Exemples de immuable types int, float et str.
Cela dit, vous ne pouvez pas faire ce que vous voulez avec
boost::python
, parce que Python lui-même ne permet pas de modifier la valeur du flotteur retourné par la fonction.Votre deuxième exemple montre une solution, une autre serait de créer mince wrappers, et en exposant que:
Qui est une meilleure solution que d'avoir à changer de classe C++.
OriginalL'auteur Bruno Oliveira
Je pense que vous voulez de retour de référence interne à la place. Je l'ai utilisé avant de faire quelque chose de similaire.
Edit: Dernière doc
le lien vers la documentation est pour la version 1.38, ce qui est très ancienne comme de ce commentaire (1.61 est en cours)
OriginalL'auteur Charles
Je ne connais pas beaucoup de coup de pouce.Python, donc je peut mal comprendre la question, auquel cas c'est complètement inutile. Mais voilà:
En Python que vous ne pouvez pas choisir entre le retour par référence ou par valeur, la distinction n'a pas de sens en Python. Je trouve que c'est plus facile de penser que tout en étant traitées par référence.
Vous avez juste des objets, et vous avez des noms pour ces objets. Donc
Crée un objet de type string "ryiuy" et vous permet alors de vous reporter à cet objet chaîne de caractères avec le nom "foo". Donc, en Python, lorsque vous obtenez passé quelque chose, vous êtes passé de l'objet. Il n'y a pas de "valeurs" en tant que tel, de sorte que vous ne pouvez pas passer la valeur. Mais là encore, il est également valide d'un point de vue qu'il ne sont pas des références soit, juste des objets et leurs noms.
Donc la réponse est, je pense, c'est que lorsque vous obtenez une référence en C, vous devez passer une référence à l'objet de référence des références en Python. Et quand vous obtenez une valeur de C, vous devez passer une référence à l'objet que vous créez à partir de cette valeur dans Python.
OriginalL'auteur Lennart Regebro
Êtes-vous sûr que le c++ objet est copié? Vous obtiendrez un nouvel objet python à chaque fois, mais qui fait référence au même objet c++. Comment allez-vous déterminer que l'objet a été copié?
Ouais, a demandé de vérifier que vous n'étiez pas à l'aide de l'id(). Quel est le message d'erreur de compilation?
C'est un boost::STATIC_ASSERTION_FAILURE, ce qui indique que quelque chose que je fais est non prises en charge ou illégale. Je ne sais pas quoi.
J'ai mis à jour mon exemple avec référence à Toto et flottent pas, ce qui fonctionne.
OriginalL'auteur Ben