Wie benutzt man die python3 c api für eine kommandozeilengesteuerte App?

Ich verwende seit einiger Zeit ein benutzerdefiniertes Build als Ersatz für virtualenv und es ist brillant. Der Aufbau dauert länger, funktioniert aber tatsächlich und es kommt nie zu Problemen.

Ein Teil davon in einem einfachen Python-Wrapper, der dem Bibliothekspfad einige bestimmte Ordner hinzufügt, was ich als sehr nützlich empfunden habe. Der Code dafür ist 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;
}

Ein Umstieg auf python3 ist also gut, oder? So...

Ich habe den Aufruf von PyString_FromString () pflichtgemäß durch PyByte_FromString () ersetzt und versucht, neu zu kompilieren, aber es treten Fehler auf:

/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

Wie Sie aus dem Fehler ersehen können, wird wchar_t anstelle von char * verwendet.

Wie solltest du diese API verwenden?

Ich sehe, dass es einige Beispiele dafür gibt, zum Beispiel:http://svn.python.org/projects/python/tags/r32rc2/Python/frozenmain.c

ernst?

Mein 29-Zeilen-Programm muss ein 110-Zeilen-Monster voller #ifdefs werden?

Habe ich ein Missverständnis oder ist die Verwendung der python3 c api wirklich so lächerlich schwierig geworden?

Ich vermisse sicherlich eine offensichtliche Komfortfunktion, die dies für Sie auf einfache, tragbare und plattformübergreifende Weise erledigt.

Antworten auf die Frage(5)

Ihre Antwort auf die Frage