2010-03-10 3 views
2

J'ai compilé un simple module C de monde de Bonjour pour Python et il fonctionne correctement dans tout ce que j'ai essayé mais IDLE. Voici ce que je tape à tester:Pourquoi mon module Python C 'hello world' fonctionne-t-il correctement dans tout sauf dans IDLE?

>>> import hello 
>>> hello.say_hello('Justin') 

Je l'ai essayé en utilisant Python à partir de l'invite de commande (j'utilise Windows), dans PyDev d'Eclipse, et avec PieDream et ils ont tous imprimer sur Hello Justin!. Cependant, dans IDLE, il n'imprime rien - il me donne juste l'invite.

Le module et setup.py que j'utilise sont de this page. Je pense que le problème est avec le compilateur. J'utilise MinGW que j'ai défini comme compilateur pour distutils dans un fichier .cfg. Je construis le module à partir de l'invite de commande avec:

python setup.py build 

et obtenir

running build 
running build_ext 
building 'hello' extension 
creating build 
creating build\temp.win32-2.6 
creating build\temp.win32-2.6\Release 
C:\MinGW\bin\gcc.exe -mno-cygwin -mdll -O -Wall -IC:\Python26\include -IC:\Python26\PC -c hellomodule.c -o build\temp.win32-2.6\Release\hellomodule.o 
writing build\temp.win32-2.6\Release\hello.def 
creating build\lib.win32-2.6 
C:\MinGW\bin\gcc.exe -mno-cygwin -shared -s build\temp.win32-2.6\Release\hellomodule.o build\temp.win32-2.6\Release\hello.def -LC:\Python26\libs -LC:Python26\PCbuild -lpython26 -lmsvcr90 -o build\lib.win32-2.6\hello.pyd 

Je pense que cela pourrait avoir quelque chose à voir avec la partie -mno-Cygwin là-dedans, mais je Je ne suis pas sûr.

Des idées ou des suggestions sur les raisons pour lesquelles ce module ne fonctionnera pas dans IDLE? Dois-je utiliser un compilateur différent?

+0

Ceci est juste une supposition, mais n'êtes-vous pas censé utiliser MSVC++ dans Windows pour Python? – Javier

+0

@javier Vous devriez pouvoir utiliser n'importe quel compilateur c. En note, j'ai suivi le tutoriel sous linux avec gcc, et idle fait la même chose: pas de sortie, mais la ligne cmd fonctionne, etc. Ok, je viens de remarquer ceci: si vous êtes inactif depuis la ligne de commande et exécutez le script , la sortie est déversée dans la fenêtre du terminal. – zdav

+0

@Javier J'ai aussi essayé d'utiliser distutils avec MSVC++ et j'ai obtenu le même résultat. –

Répondre

5

Sonne comme le salut écrit directement à stdout. stdout de Python est pas nécessairement au même endroit que C stdout

Normalement, vous devez retourner une chaîne Python et Python peut imprimer à son propre stdout

+0

Oui, je pense que tu as raison. Si je 'sys d'importation', 'sys.stdout' est différent dans IDLE par rapport aux autres endroits où je courais le module. IDLE définit 'sys.stdout' sur quelque chose du module idlelib. –

+0

@Justin, maintenant pour voir si vous pouvez convertir la chaîne C en Python str et le retourner :) –

+0

Piece of cake. En avant et vers le haut! Étrange que la plupart des exemples que j'ai vus ont utilisé printf quand il est apparemment plus approprié de retourner une chaîne. –

5

Si vous devez écrire à Python sys.stdout d'un code C- extension, vous pouvez utiliser quelque chose comme:

void writeout(const char* nullterminated) 
{ 
    PyObject* sysmod = PyImport_ImportModuleNoBlock("sys"); 
    PyObject* pystdout = PyObject_GetAttrString(sysmod, "stdout"); 
    PyObject* result = PyObject_CallMethod(pystdout, "write", "s", nullterminated); 
    Py_XDECREF(result); 
    Py_XDECREF(pystdout); 
    Py_XDECREF(sysmod);  
} 

(plus, sans doute, vérifier un peu d'erreur - juste pour la santé mentale, au cas où quelqu'un a fait quelque chose de fou comme del sys.stdout & c ;-). Bien sûr, si vous avez besoin de plusieurs écritures, il peut être plus efficace d'obtenir stdout qu'une seule fois, de le conserver aussi longtemps que nécessaire, et de le décréer une seule fois lorsque vous avez fini d '«imprimer» des choses (mais ne vous comportez pas correctement dans les cas où votre appelant Python réaffecte sys.stdout pendant que vous maintenez une référence à sa version précédente: vous continuerez à imprimer sur la version précédente, comme le ferait un module codé en Python similaire. Cette recherche répétée équivaut à faire sys.stdout.write(somestring) en Python, qui regarde aussi les choses à chaque fois - un peu plus lent mais "sémantiquement plus sûr" au cas où votre appelant Python fait des choses "assez énervé" avec sys.stdout (comme vous l'avez trouvé sur ce que fait IDLE ;-). ((Pas si énervé, vraiment, alors vous voudrez peut-être le supporter correctement ;-)).

+1

J'ai modifié le code pour ce qui a effectivement été compilé pour moi, mais je vous ai quand même donné +1 parce que vous m'avez mis dans la bonne direction de ce que je devais faire. – CashCow