2016-02-01 1 views
2

J'enroulant cette lib avec Python SWIG qui a une fonction qui ressemble à ceci:Emballage un argument vide de * en Python SWIG

int set_option(Foo *foo, const char *name, void *value); 

Dans la lib const char *name est mis en correspondance avec un type que j'ai accès à regarder : int, char *, char **.

Le code wrapper généré par défaut accepte uniquement un void * (naturellement) enveloppé. Quelle est la meilleure façon de faire accepter la méthode encapsulée par un objet Python comme argument, et de faire la vérification de type, et la conversion de Python en C dans mon propre code C? Je pense que ce serait une sorte de carte de type, mais hélas, je ne peux pas le comprendre.

@Goodies

In [12]: lib.set_option(foo, "option", "value") 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-12-4ccf706b5c50> in <module>() 
----> 1 lib.set_option(foo, "option", "value") 

TypeError: in method 'set_option', argument 3 of type 'void *' 
+1

Je ne comprends probablement pas cela correctement, mais ne prenez-vous pas généralement un pointeur PyObject comme un argument et analyser les arguments dans C? Il ne devrait pas accepter un objet spécifique par défaut afaik. Nouveau à CPython, cependant. – Goodies

+0

Envie de poster ça dans OP? C'est difficile à voir dans les commentaires. – Goodies

+0

@Goodies: Oui, le formatage n'est pas bien dans le commentaire. – totoro

Répondre

2

Si vous voulez juste passer un PyObject à quelque chose en utilisant %extend vous pouvez modifier ce que vous avez et simplement écrire:

%extend Foo { 
    int set_option(const char *name, PyObject *value) { 
      // Here value is now a PyObject *, so work with that. 
      // $self is Foo *foo 
      return 0; 
    } 
}; 

Il n'y a pas besoin d'un typemap et cette fonction maintenant accepte toute entrée Python. Ce que vous en faites dépend de vous et si vous conservez l'objet, vous devrez augmenter le nombre de références.

+0

Oui, c'est tout ce que je veux faire. Je n'étais pas au courant que SWIG a permis cela. – totoro

1

Transforme que c'était assez simple. Je voulais value comme PyObject * afin que je puisse taper vérifier et convertir moi-même. Voici la fonction que je voulais envelopper:

int set_option(Foo *foo, const char *name, void *value); 

Cette solution permet également une méthode de class Foo.

%extend Foo { 
     int set_option(const char *name, void *value) { 
       // Here value is now a PyObject *, so work with that. 
       // $self is Foo *foo 
       return 0; 
     } 
}; 

%typemap(in) (void *value) { 
     $1 = (void *) $input; 
}; 
+0

Je pense que vous aurez un problème de comptage de référence ici, en fonction de ce que vous faites dans set_option, donc vous aurez besoin d'un Py_INCREF ($ input) dans le typemap et un moyen d'arranger plus tard – Flexo

+0

I don ' Je le pense dans mon cas. Je ne fais qu'extraire l'information en C et en faire une copie. Je ne garde aucune référence à des données appartenant à un objet Python. – totoro

+0

Je ne peux pas poster mon code réel en raison de la non-divulgation. – totoro