Python работает на C ++ в режиме отладки, но не в исполняемом файле - PullRequest
0 голосов
/ 04 марта 2019

Я работаю над внедрением кода Python в программу helloworld на c ++, необходимые дополнительные каталоги include / library правильно настроены.

Когда я использую локальный отладчик Windows, он правильно показывает «Hello World». Но если я дважды щелкну на project.exe, он скажет, что project.exe перестал работать.

Кто-нибудь знает, какие конфигурации или шаги нужно сделать, чтобы project.exe показывал «Hello World»?"когда дважды щелкнул ??

Код выглядит следующим образом:

main.cpp

#include <iostream>
#include <Python.h> 
#include <string.h>
#include <stdlib.h>
using namespace std;
int main() 
{ 
    Py_Initialize(); 
    PyRun_SimpleString("import sys");   
    PyRun_SimpleString("sys.path.append('./')");
    PyObject *pModule = PyImport_ImportModule("helloworld");
    PyObject *pFunc = PyObject_GetAttrString(pModule, "printHello");
    PyEval_CallObject(pFunc, NULL);
    Py_Finalize();
    return 0;
}

helloworld.py

def printHello():
   print("Hello World!")

1 Ответ

0 голосов
/ 04 марта 2019

Выстрел в темноте:

  • Вы не проверяете возвращаемые значения для своих вызовов, особенно те, которые возвращают указатели
  • , работающие с отладчиком, не используют то же самоекаталог как метод exe-click

, вы должны проверить возвращаемое значение pModule.Я предполагаю, что, поскольку вы находитесь в другом каталоге, импорт завершается неудачно, поэтому функция PyImport_ImportModule возвращает NULL (python вызывает исключения, но не в этом контексте, поскольку это C API с его ограничениями)

Это хрупко (и, возможно, бесполезно):

sys.path.append('./')

Вы не знаете, что такое текущий каталог.Было бы лучше сделать его относительно текущего исполняемого файла или настроить с помощью аргумента или переменной среды.Вы можете сделать это относительно текущего исполняемого файла, см. Поиск пути к текущему исполняемому файлу без / proc / self / exe или Получить путь к исполняемому файлу

Теперь, когда вы пытаетесьчтобы использовать этот нулевой указатель, программа падает.Начните с этого:

PyObject *pModule = PyImport_ImportModule("helloworld");
if (pModule == NULL)
{
   std::cout << "could not import module\n";
   exit(1);
}

(то же самое относится и к атрибуту fetch: всегда защищайте свои вызовы или, что лучше: оберните их в метод C ++, который генерирует исключения).

#include <string>
#include <stdexcept>

PyObject *safe_PyImport_ImportModule(const std::string &module_name)
{
   PyObject *pModule = PyImport_ImportModule(module_name.c_str());
   if (pModule == NULL) // c++11 purists would put "nullptr"
   {
       std::cout << "cannot import " << module_name << '\n';
       throw std::runtime_error("Import error: "+module_name);
   }
   return pModule;
}
...