为什么我的'hello world' Python C模块在除IDLE外都正常工作?

2 投票
2 回答
1074 浏览
提问于 2025-04-15 20:16

我编译了一个简单的“你好,世界”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 个回答

5

如果你需要从用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会这样做;-)。其实并没有那么边缘,所以你可能想要好好支持一下;-)。

5

听起来这个 hello 是直接写到 stdout 的。Python 的 stdout 不一定和 C 语言的 stdout 是同一个地方。

通常你会把一个字符串返回给 Python,这样 Python 就可以把它打印到自己的 stdout 上。

撰写回答