Segfault lors de l'appel D'une fonction Python à partir de C
donc, je veux appeler une fonction de rappel Python de C.
à un moment donné, la fonction est envoyée à C et emballée dans un tuple comme celui-ci
PyObject *userData = Py_BuildValue("Oi",py_callback,some_number);
quelque part dans cette zone, je fais aussi Py_INCREF(py_callback)
.
Plus tard dans le programme, je veux appeler cette fonction
PyObject *py_callback;
int some_number;
PyArg_ParseTuple((PyObject*)userData,"Oi",&py_callback,&some_number); // returns true
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callback,
/* ... */
NULL);
et ce dernier appel provoque un défaut de segmentation. Avez-vous une idée, pourquoi il ferait une telle chose?
2 réponses
Lorsqu'on obtient un comportement bizarre de L'API Python C, il est toujours utile de vérifier deux fois que vous gérez correctement l'état du verrou de L'interpréteur Global (alias "the GIL"): http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock
Je ne sais pas pourquoi tout le monde parle de la GIL ici. Vous le relâchez quelque part? Je remarque quelques problèmes possibles que je vais énumérer ci-dessous. C'est mêlé de suggestions.
je remarque que vous n'incrémentez pas le nombre de référence de userData
. Pourquoi pas? Vous êtes le ranger n'est-ce pas? Pourquoi voulez-vous le stocker dans le tuple? Pourquoi ne pas simplement garder deux variables (pour callback et données) et ensuite incrémenter leurs recomptages de sorte que vous possédez un de référence?
tout d'abord, vérifiez les valeurs de retour de toutes vos fonctions pour voir si elles sont NULL
. Cela vous permettra de vous assurer que vous êtes réellement fonctionner correctement. Il est également probablement une bonne idée d'utiliser PyObject_Print
pour imprimer les objets qui vous intéressent à tous les points du code pour s'assurer que les choses vont comme vous vous attendez.
D'après votre commentaire sur l'endroit où le segfault se produit, je pense que vous passez le mauvais nombre de les paramètres de votre fonction de rappel lorsque vous l'appelez avec PyObject_CallFunctionObjArgs
. Pouvez-vous vérifiez? Montrez-nous la définition de votre fonction de rappel et vérifiez à nouveau l'invocation.
un autre problème possible que je vois est que du nom, py_some_number
sonne comme vous attendez un objet Python entier. Ce n'est pas le cas. Après le PyArg_ParseTuple
, il contiendra un entier.