我一直在使用自定义构建作为virtualenv的替代品一段时间了,而且它很棒.它需要更长的时间来构建,但实际上它可以工作,并且它永远不会搞砸.
部分内容在一个简单的python包装器中,它将一些特定的文件夹添加到库路径中,我发现它非常有用.它的代码是微不足道的:
#include <stdio.h>
#include <n/text/StringUtils.h>
#include <Python.h>
int main(int argc, char *argv[]) {
/* Setup */
Py_SetProgramName(argv[0]);
Py_Initialize();
PySys_SetArgv(argc, argv);
/* Add local path */
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
/* Custom path */
char *cwd = nrealpath(argv[0]);
char *libdir = nstrpath(cwd, "python_lib", NULL);
PyList_Append(path, PyString_FromString(libdir));
free(cwd);
free(libdir);
/* Run the 'main' module */
int rtn = Py_Main(argc, argv); // <-- Notice the command line arguments.
Py_Finalize();
return rtn;
}
Run Code Online (Sandbox Code Playgroud)
那么,转向python3是对的吗?所以...
我尽职尽责地用PyByte_FromString()替换了对PyString_FromString()的调用并尝试重新编译,但它引发了错误:
/Users/doug/env/src/main.c:8:21: error: incompatible pointer types passing 'char *' to parameter of type 'wchar_t *' (aka 'int *')
[-Werror,-Wincompatible-pointer-types]
Py_SetProgramName(argv[0]);
^~~~~~~
/Users/doug/projects/py-sdl2/py3/include/python3.3m/pythonrun.h:25:45: note: passing argument to parameter here
PyAPI_FUNC(void) Py_SetProgramName(wchar_t *);
^
/Users/doug/env/src/main.c:10:23: error: incompatible pointer types passing 'char **' to parameter of type 'wchar_t **' (aka 'int **')
[-Werror,-Wincompatible-pointer-types]
PySys_SetArgv(argc, argv);
^~~~
/Users/doug/projects/py-sdl2/py3/include/python3.3m/sysmodule.h:12:47: note: passing argument to parameter here
PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **);
^
/Users/doug/env/src/main.c:24:27: error: incompatible pointer types passing 'char **' to parameter of type 'wchar_t **' (aka 'int **')
[-Werror,-Wincompatible-pointer-types]
int rtn = Py_Main(argc, argv);
^~~~
/Users/doug/projects/py-sdl2/py3/include/python3.3m/pythonrun.h:148:45: note: passing argument to parameter 'argv' here
PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
^
3 errors generated.
make[2]: *** [CMakeFiles/python.dir/src/main.c.o] Error 1
make[1]: *** [CMakeFiles/python.dir/all] Error 2
make: *** [all] Error 2
Run Code Online (Sandbox Code Playgroud)
从错误中可以看出,使用wchar_t而不是char*.
你怎么用这个api?
我看到有一些例子可以做到这一点,例如:http: //svn.python.org/projects/python/tags/r32rc2/Python/frozenmain.c
当真?
我的29线程序必须成为一个充满#ifdefs的110线怪物?
我误解了,还是python3 c api真的变得非常难以使用?
当然,我缺少一些明显的便利功能,它以简单,便携和跨平台的方式为您做到这一点?
从转换的官方推荐的方式char来wchar_t为通过Py_DecodeLocale.像这样:
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
Py_SetProgramName(program);
Run Code Online (Sandbox Code Playgroud)
我自己花了很多时间寻找答案。我拼凑了其他人的评论,并构建了此代码片段以将 char** argv 转换为 wchar_t** 类型:
wchar_t** _argv = PyMem_Malloc(sizeof(wchar_t*)*argc);
for (int i=0; i<argc; i++) {
wchar_t* arg = Py_DecodeLocale(argv[i], NULL);
_argv[i] = arg;
}
Py_Initialize();
PySys_SetArgv(argc, _argv);
Run Code Online (Sandbox Code Playgroud)
到目前为止,效果很好。我已经确认我的嵌入式 Python 代码正确接收了命令行参数。