2017-08-31 1 views
2

J'essaye d'enrouler du code C++ qui utilise des structures avec des constructeurs, et de ne pas comprendre comment.Appelez directement le constructeur de structure C++ à partir de cython

C++ struct:

typedef struct point_3d_t 
{ 
    double x; 
    double y; 
    double z; 

    point_3d_t(double x, double y, double z) 
     : x(x) 
     , y(y) 
     , z(z) 
     {} 

} point_3d; 

wrapper Cython:

cdef extern from "./cppdar.hpp": 
    ctypedef struct point_3d: 
     point_3d(double, double, double) 
     double x; 
     double y; 
     double z; 

Maintenant, je serais attendre pouvoir construire la struct par quelque chose comme cdef point_3d p1(v, v, v) (à partir du fichier cython) , mais je n'arrive pas à comprendre comment utiliser Cython pour utiliser le constructeur fourni.

J'ai essayé:

  • cdef point_3d p1(v, v, v)
  • cdef point_3d p1 = point_3d(v, v, v)
  • cdef point_3d p1(0, 0, 0)
  • cdef point_3d p1 = point_3d(0, 0, 0)

v est un cdef double v = 0 explicite, mais aucun travail.

En utilisant cdef point_3d p1, p1.x = nnnn, etc ..., mais c'est ennuyeux, et je ne vois pas pourquoi je ne devrais pas être en mesure d'utiliser le constructeur par défaut, je pense.

Essayer de rechercher le problème donne beaucoup de fouillis liés aux constructeurs de classe, ce qui n'a pas été utile.

Répondre

1

Ok, donc la réponse est que vous ne pouvez pas pile allouer des objets C++ avec des arguments de constructeur cython, essentiellement du tout:

De: https://groups.google.com/forum/#!topic/cython-users/fuKd-nQLpBs

Oui, c'est une limitation, mais c'est un problème plus fondamental que l'analyseur syntaxique . La construction et la destruction des objets de pile allouée dans C++ est intimement liée à leur champ d'application et les règles de cadrage sont différents en Python et C. Par exemple, considérons

if some_condition(): 
    x = Foo(1) 
else: 
    x = Foo(2, 3) 
return x.method() 

cela ne peut pas être exprimé en tant que telle en C++. Inversement

if (some_other_condition()) { 
    Foo_with_RIAA foo(x) 
} 
... 

ne traduirait pas "correctement" les règles de portée Python.

Maintenant il y a des cas où il pourrait avoir un sens, mais des changements importants de génération de code devrait être fait, comme actuellement toutes les variables sont déclarées en haut d'une fonction (à suivre la norme C89 , dont certains les compilateurs appliquent) mais en mode C++ nous aurions pour reporter la déclaration de la variable à son instanciation (en évitant notamment les étendues de niveau C insérées automatiquement { pour simplifier la génération de code).

Comme on peut toujours allouer de tels objets compliqués sur le tas, ce n'est pas une limitation significative.

C'est extra-double, plus ennuyeux, parce que cela signifie que vous ne pouvez pas simplement classes wrap qui ne disposent pas des constructeurs par défaut dans de nombreux cas.


L'horrible, sans bonne solution de contournement hacky est d'envelopper les constructeurs dans une simple fonction C (++), puis exposer que via cython.

+0

Je ne suis pas sûr de comprendre ce que votre travail vous apporte? Vous avez toujours besoin d'un constructeur par défaut pour être disponible je pense. – DavidW

+0

@DavidW - Oui, vous obtenez toujours un processus de construction, de construction et de déplacement, mais c'est beaucoup mieux qu'instancier par défaut, puis de définir les membres individuellement. –

+0

Je crois que Cython peut faire la construction puis l'affectation de l'assignation/déplacement: 'cdef point_3d p' puis plus tard' p = point_3d (...) '. Vous pourriez avoir besoin de le dire sur le constructeur par défaut ainsi que celui que vous utilisez. – DavidW