I have been using custom assembly to replace virtualenv for a while, and it is brilliant. It will take longer, but it really works, and it never gets screwed.
Part of this is in a simple python shell that adds some specific folders to the library path, which I found very useful. The code for it is trivial:
#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; }
So is switching to python3 good? So that...
I dutifully replaced the call to PyString_FromString () with PyByte_FromString () and tried to recompile, but it causes errors:
/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.co] Error 1 make[1]: *** [CMakeFiles/python.dir/all] Error 2 make: *** [all] Error 2
As you can see from the error, wchar_t is used instead of char *.
How should you use this api?
I see that there are several examples of this, for example: http://svn.python.org/projects/python/tags/r32rc2/Python/frozenmain.c
Really?
Should my 29-line program become a 110-line monster full of #ifdefs?
Do I really not understand, or is that python3 c api really getting so ridiculously difficult to use?
Have I really missed some obvious convenience feature that does this for you in a simple, portable, and cross-platform way?