0

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.

0 Answers0