I am building a DLL to embed Python 2.7 (2.7.18 to be specific) in a larger application largely following python.org's C API documentation. When I believe I am applying Py_DECREF
correctly to a PyString PyObject
, any linking application crashes without error. The code is largely copied from a similar application built with python 3.8, 3.9 and 3.10 that in fact works.
// python_functions.h
__declspec(dllexport) int init_python();
// python_functions.c
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdio.h> // printf
#include <string.h>
//#include <wchar.h> // wchar_t for python3 only
#include "python_functions.h"
__declspec(dllexport) int init_python() {
int rv = -1;
printf("attempting to initialize Python interpreter...\n");
// I have other python versions, Python27 not on path. set PYTHONHOME
Py_SetPythonHome("C:\\Python27\\"); // python27
//Py_SetPythonHome(L"C:\\Python38\\"); // python3X
Py_Initialize();
PyObject * pModule_Name = PyString_FromString("python_functions"); // python27 only
//PyObject * pModule_Name = PyUnicode_FromString("python_functions"); // python3X
if (!pModule_Name) {
printf("failed to convert module name to python string object\n");
return rv;
}
// can confirm pModule_Name != NULL && Py_REFCNT(pModule_Name) == 1 here
/*
load python module named "python_functions"
*/
// can also confirm pModule_Name != NULL && Py_REFCNT(pModule_Name) == 1 here
//Py_DECREF(pModule_Name); // If I uncomment this line, application linking .dll crashes
printf("pModule_Name successfully used\n");
rv = 0;
return rv;
}
// main.c
#include <stdio.h>
#include "python_functions.h"
int main(int argc, char **argv) {
int rv = 0;
// crashes without error if Py_DECREF(pModule_Name) in python_functions.c uncommented
printf("%d\n", init_python());
return rv;
}
Compiling the .dll with gcc 8.1.0 (MinGW-64) linking against C:\Python27\python27.dll:
gcc -IC:\Python27\include -LC:\Python27\libs -IC:\Python27 python_functions.c -shared -o python_functions.dll -lpython27
Compiling main with python27.dll and python_functions.dll in the same directory:
gcc main.c -o main.exe -L./ -lpython_functions
If I uncomment the line Py_DECREF(pModule_Name)
, which I thought I must do since PyString_FromString
returns a new reference, then running main.exe
crashes without return.
Should I be using something else or not doing reference counting on result from PyString_FromString
or is this a larger problem with linking to python27?
If I make the commented/corresponding compiler changes to link against python 3.8+, no problems...
The only differences I know of are the significant changes to the Python C API between 2.7 and e.g. 3.8+ as well as the differences in python 2.X vs 3.X string representations. I believe PyString is appropriate here because when I actually implement and load a module name python_functions.py
, it works...so long as I leave Py_DECREF(pModule_Name)
commented out and the pointer leaked.
I also thought PyString_FromString
might have a problem passing a string literal, but it accepts a const char *
, documentation says it creates a copy, and even passing a copy of the string literal to another variable does not work.