为什么我的'hello world' Python C模块在除IDLE外都正常工作?
我编译了一个简单的“你好,世界”C模块,用于Python,测试下来在我尝试的所有地方都能正常工作,除了IDLE。以下是我用来测试的代码:
>>> import hello
>>> hello.say_hello('Justin')
我在命令提示符下(我用的是Windows)、Eclipse的PyDev和PieDream中都试过,结果都能打印出Hello Justin!
。但是在IDLE中,它什么都不打印,只是给我一个提示符。
我使用的模块和setup.py
来自这个页面。我觉得问题可能出在编译器上。我使用的是MinGW,并在一个.cfg文件中把它设置为distutils的编译器。我是通过命令提示符来构建这个模块的,命令是:
python setup.py build
然后我得到了
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
我在想,这可能和里面的-mno-cygwin部分有关,但我不太确定。
有没有人能给点建议,为什么这个模块在IDLE中不工作?我是否应该换一个编译器?
2 个回答
如果你需要从用C语言写的扩展中向Python的 sys.stdout
输出内容,可以使用类似下面的代码:
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);
}
当然,最好再加一点错误检查,以防有人做了一些疯狂的事情,比如 del sys.stdout
等等。
如果你需要多次输出,可能更高效的做法是只获取一次 stdout
,然后在需要的时候一直用它,最后只在完成“打印”后减少一次引用计数(decref)。不过,这样做在你的Python调用者重新赋值 sys.stdout
的时候可能会出现问题:你会继续向之前的版本输出,就像用Python写的模块一样。这种重复查找就像在Python中每次都执行 sys.stdout.write(somestring)
,每次都会查找,虽然稍微慢一点,但在你的Python调用者做一些“比较边缘”的操作时,这样做会更安全(就像你发现IDLE会这样做;-)。其实并没有那么边缘,所以你可能想要好好支持一下;-)。
听起来这个 hello 是直接写到 stdout
的。Python 的 stdout
不一定和 C 语言的 stdout
是同一个地方。
通常你会把一个字符串返回给 Python,这样 Python 就可以把它打印到自己的 stdout
上。