制作一个需要其他扩展的Python C扩展
我有几个Python函数,用来让用Pygame开发游戏变得更简单。我把这些函数放在一个叫helper.py的文件里,这个文件在我的Python路径下,所以我可以在我做的任何游戏中导入它们。我想通过这个练习来学习Python扩展,把这个模块转换成C语言。不过,我遇到的第一个问题是,我需要使用Pygame中的一些函数,但我不确定这是否可行。Pygame安装了一些头文件,但似乎没有Python函数的C版本。也许我漏掉了什么。
我该怎么解决这个问题呢?目前的解决办法是这个函数接受一个函数参数并调用它,但这并不是最理想的解决方案。
顺便说一下,我使用的是Windows XP,Python 2.6和Pygame 1.9.1。
3 个回答
在pygame
模块中,大部分功能其实都是对SDL功能的封装,也就是说,如果你想了解这些功能的C语言版本,就要去看SDL的相关内容。pygame.h
文件里定义了一系列的import_pygame_*()
函数。在扩展模块初始化时,调用一次import_pygame_base()
和其他函数,就可以访问到pygame模块所需的C语言接口(这些接口在每个头文件中都有定义)。你可以在谷歌代码搜索中找到一些示例。
你可以从C代码中导入Python模块,并像在Python代码中一样调用里面定义的内容。虽然这个过程有点繁琐,但完全是可行的。
当我想弄明白怎么做这种事情时,我会查看C API文档。里面关于导入模块的部分会对你有帮助。你还需要了解如何读取属性、调用函数等等,这些内容都在文档里。
不过,我怀疑你真正想做的是从C代码中调用底层库sdl。这是一个C语言的库,用C语言调用起来非常简单。
下面是一些示例代码,展示如何在C中导入一个Python模块,这段代码是从一段有效的代码中改编而来的。
PyObject *module = 0;
PyObject *result = 0;
PyObject *module_dict = 0;
PyObject *func = 0;
module = PyImport_ImportModule((char *)"pygame"); /* new ref */
if (module == 0)
{
PyErr_Print();
log("Couldn't find python module pygame");
goto out;
}
module_dict = PyModule_GetDict(module); /* borrowed */
if (module_dict == 0)
{
PyErr_Print();
log("Couldn't find read python module pygame");
goto out;
}
func = PyDict_GetItemString(module_dict, "pygame_function"); /* borrowed */
if (func == 0)
{
PyErr_Print();
log("Couldn't find pygame.pygame_function");
goto out;
}
result = PyEval_CallObject(func, NULL); /* new ref */
if (result == 0)
{
PyErr_Print();
log("Couldn't run pygame.pygame_function");
goto out;
}
/* do stuff with result */
out:;
Py_XDECREF(result);
Py_XDECREF(module);
在编程中,有时候我们会遇到一些问题,尤其是在使用某些工具或库时。比如,有人可能会在使用某个库的时候,发现它的某些功能不太好用,或者不太符合自己的需求。这种情况下,大家通常会在网上寻找解决方案,比如在StackOverflow上提问。
在提问时,描述问题的方式很重要。你需要清楚地说明你遇到的具体问题,提供一些代码示例,甚至可以说明你尝试过哪些解决方法。这样,其他人才能更好地理解你的问题,并给出有效的建议。
总之,提问时要尽量详细和清晰,这样才能更快找到解决办法。
/* get the sys.modules dictionary */
PyObject* sysmodules PyImport_GetModuleDict();
PyObject* pygame_module;
if(PyMapping_HasKeyString(sysmodules, "pygame")) {
pygame_module = PyMapping_GetItemString(sysmodules, "pygame");
} else {
PyObject* initresult;
pygame_module = PyImport_ImportModule("pygame");
if(!pygame_module) {
/* insert error handling here! and exit this function */
}
initresult = PyObject_CallMethod(pygame_module, "init", NULL);
if(!initresult) {
/* more error handling &c */
}
Py_DECREF(initresult);
}
/* use PyObject_CallMethod(pygame_module, ...) to your heart's contents */
/* and lastly, when done, don't forget, before you exit, to: */
Py_DECREF(pygame_module);