2009-12-02 3 views
1

J'ai un type de valeur C++ encapsulé avec Boost.Python qui a un concept de valeur NULL. Les parties pertinentes du code wrapper apparaissent comme suit:Boost.Python: __init__ acceptant Aucun argument

class_<TCurrency> currency("TCurrency") 
    .def(init<long>()) 
    .def(init<const std::string&>()) 
    <...>; 

Actuellement, en essayant de créer une instance NULL en Python en passant None la méthode __init__() provoque le C++ cteur accepter une référence de chaîne const à être appelée avec un invalide référence. (&arg == NULL)

Est-il possible de piéger le cas où None est passé à un constructeur et de le gérer avec élégance ou au moins de lancer une exception significative avant que mon programme se bloque? Utilisation de Boost 1.36 et Python 2.6.2.

Répondre

2

Ajout d'une surcharge init<void*> passera NULL si None est utilisé, mais je ne suis pas sûr de savoir comment cela pourrait affecter d'autres ctors dans les cas de coin. Je ne reçois pas non plus la même chaîne que & conversion que vous mentionnez, si je pars init<void*>. En utilisant Boost.Python 1.37 et Python 2.6.2.

Exemple:

#include <iostream> 
#include <string> 

#include <boost/python.hpp> 


struct A { 
#define BODY { std::cout << __PRETTY_FUNCTION__ << '\n'; } 
    A() BODY 
    A(long) BODY 
    A(std::string const&) BODY 
    A(void* p) BODY 
#undef BODY 
}; 

BOOST_PYTHON_MODULE(ex) { 
using namespace boost::python; 
class_<A>("A") 
    .def(init<long>()) 
    .def(init<std::string const&>()) 
    .def(init<void*>()) 
; 
} 
 
>>> import ex 
>>> ex.A() 
A::A() 
<ex.A object at 0x839bf7c> 
>>> ex.A(42) 
A::A(long int) 
<ex.A object at 0x839bfcc> 
>>> ex.A("abc") 
A::A(const std::string&) 
<ex.A object at 0x839bf7c> 
>>> ex.A(None) 
A::A(void*) 
<ex.A object at 0x839bfcc> 

Si init<void*> est laissé:

 
>>> ex.A(None) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    A.__init__(A, NoneType) 
did not match C++ signature: 
    __init__(_object*, std::string) 
    __init__(_object*, long) 
    __init__(_object*) 
+0

Il ne semble qu'il devrait y avoir un adaptateur ou similaire, vous devriez être en mesure d'appliquer, par exemple, make A (None) utilise le ctor par défaut. Je suis content que vous ayez posé cette question et j'attendrai avec impatience une réponse plus détaillée. (De quelqu'un d'autre ..><) –

+0

Intéressant. Je ne veux pas vraiment modifier la classe C++ d'origine pour accepter un void *, mais j'ai tenté de définir un __init__ en dehors de la classe. Il ne crée pas réellement un objet correctement (cela fera l'objet d'une autre question) mais au moins j'obtiens un tb Python au lieu d'un crash. Yay! =] –

Questions connexes