0

I am trying a really basic "hello world" program, which should embedd a python script in my C++ console application, but it fails at pModule = PyImport_Import(pName); with an unspecified exception "Access violation reading location ..."

I was already able to run PyRun_SimpleFile() for a python script without definitions and returns, but for my future application I need a python method with returns, so PyRun_SimpleFile() is not an option.

My code, based on this Introduction is:

main.cpp

#include "stdafx.h"
#include <stdlib.h>
#include <Python.h>

int main(int argc, char *argv[])
{
    PyObject *pName, *pModule;
    PyObject *pFunc, *pValue;

    pName = PyUnicode_FromString("HelloWorld");
    pModule = PyImport_Import(pName);
    Py_XDECREF(pName);

    if (pModule)
    {
        pFunc = PyObject_GetAttrString(pModule, "getInteger");
        if (pFunc && PyCallable_Check(pFunc))
        {
            pValue = PyObject_CallObject(pFunc, NULL);
            printf_s("C: getInteger() = %ld\n", PyLong_AsLong(pValue));
            Py_XDECREF(pValue);
        }
        else
        {
            printf("ERROR: function getInteger()\n");
        }
        Py_XDECREF(pFunc);
    }
    else
    {
        printf_s("ERROR: Module not imported\n");
    }

    Py_XDECREF(pModule);

    Py_Finalize();
    return 0;
}

HelloWorld.py (in Debug Location of my VS2015 Solution):

def getInteger():
    print('Python function getInteger() called')
    c = 100*2
    return c
shup
  • 120
  • 1
  • 16

1 Answers1

3

Well, I believe some instructions is lacking in your code, like Py_Initialize. I also would use PyImport_ImportModule instead of PyImport_Import. See this sequence that you could be trying:

int main(int argc, char *argv[])
{
    Py_SetPythonHome(L"path/to/python/folder");
    Py_Initialize();
    //PySys_SetArgv(argc, argv); //optional, argv must be wchar_t
    PyObject *pFunc, *pValue;

    pModule = PyImport_ImportModule("HelloWorld");

    if (pModule)
    {
        pFunc = PyObject_GetAttrString(pModule, "getInteger");
        if (pFunc && PyCallable_Check(pFunc))
        {
            pValue = PyObject_CallObject(pFunc, NULL);
            printf_s("C: getInteger() = %ld\n", PyLong_AsLong(pValue));
            Py_XDECREF(pValue);
        }
        else
        {
            printf("ERROR: function getInteger()\n");
        }
        Py_XDECREF(pFunc);
    }
    else
    {
        printf_s("ERROR: Module not imported\n");
    }

    Py_XDECREF(pModule);

    Py_Finalize();
    return 0;
}

If still not working, try adding this after PyInitialize:

PyRun_SimpleString(
    "import os, sys \n"
    "sys.path.append(os.getcwd()) \n"
);

Also after PyInitialize, you can check if it's initialized with Py_IsInitialized.

João Paulo
  • 6,300
  • 4
  • 51
  • 80
  • Thanks a lot! The missing `Py_Initialize` solved it! But now I'm stuck on a read access violation on Py_Finalize. Any ideas on that too? – shup May 31 '19 at 14:11
  • Try not to `Py_XDECREF(pModule)`. Remove this line and see if it stops crashing. – João Paulo May 31 '19 at 15:38
  • This did not change it, unfortunately. But I found out that the heap gets corrupted, but I can't really figure out where? – shup Jun 03 '19 at 09:55
  • 1
    Since this is unrelated to the original question, I decided to open up a new one. Thanks for your help! – shup Jun 03 '19 at 11:39