Как можно получить доступ к модулю Python на С++?

Я пытаюсь импортировать модуль на С++; модуль находится в пакете и должен быть доступен следующим образом:

from x.y import class1,func1, const1, etc 

Я использую Python 3.6, и для этой версии я нашел, что нужно использовать PyRun_SimpleString для импорта, а затем использовать PyImport_AddModuleObject для обработки моего модуля. то есть:

PyRun_SimpleString("from PacKage1 import Module1 as Module1");
auto module = PyImport_AddModuleObject(PyUnicode_DecodeFSDefault("Module1"));

так что в будущем я могу получить доступ к его различным атрибутам, что-то вроде этого:

auto args = Py_BuildValue("sOOOOONNiN", model_name, model_checkpoint_path, align_fn,
                          bank_folder_root, cache_folder, postfix, 
                          rebuild_cache, use_jit, threshold, device);

if (module != nullptr) {
    // dict is a borrowed reference.
    auto pdict = PyModule_GetDict(module);
    if (pdict == nullptr) {
        cout << "Fails to get the dictionary.\n";
        return 1;
    }
    //Py_DECREF(module);
    PyObject *pKeys = PyDict_Keys(pdict);
    PyObject *pValues = PyDict_Values(pdict);

    map<string, string> my_map;
    //cout << "size: " << PyDict_Size(pdict)<<endl;

    char* cstr_key = new char[100];
    char* cstr_value = new char[500];

    for (Py_ssize_t i = 0; i < PyDict_Size(pdict); ++i) {
        PyArg_Parse(PyList_GetItem(pKeys, i), "s", &cstr_key);
        PyArg_Parse(PyList_GetItem(pValues, i), "s", &cstr_value);
        //cout << cstr<< "  "<< cstr2 <<endl;
        my_map.emplace(cstr_key, cstr_value);
    }
    for (auto x : my_map)
    {
        cout << x.first << " : " << x.second << endl;
    }
    system("pause");

    // Builds the name of a callable class
    auto python_class = PyDict_GetItemString(pdict, "MyClass1");

    system("pause");
    if (python_class == nullptr) {
        cout << "Fails to get the Python class.\n";
        return 1;
    }
    //Py_DECREF(pdict);


    cout << python_class;
    PyObject* object;

    // Creates an instance of the class
    if (PyCallable_Check(python_class)) {
        object = PyObject_CallObject(python_class, args);
        Py_DECREF(python_class);
    }
    else {
        std::cout << "Cannot instantiate the Python class" << endl;
        Py_DECREF(python_class);
        return 1;
    }

    auto val = PyObject_CallMethod(object, "is_jit_model_available", NULL);
    if (!val)
        cout << "error!";

    cout << val;

Когда я пытаюсь запустить этот код, я получаю этот вывод, который показывает содержимое карт:

size: 5
__doc__ : Module1
__loader__ : Module1
__name__ : Module1
__package__ : Module1
__spec__ : Module1

Итак, это результат PyModule_GetDict(module); Однако, когда дело доходит до извлечения класса из этого модуля, происходит сбой, то есть PyDict_GetItemString(pdict, "MyClass1"); возвращает null.

Мне кажется, что сам обработчик модуля неверен, и это, вероятно, потому, что, возможно, он не указывает на фактический модуль, что означает, что я полностью не смог импортировать и получить дескриптор этого модуля.

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

Что мне здесь не хватает?


person Rika    schedule 25.03.2020    source источник
comment
Рассматривали ли вы возможность использования фреймворка C++ для встраивания Python? Например, Boost Python (или другие)? Такие рамки обычно облегчают задачу.   -  person Some programmer dude    schedule 25.03.2020
comment
Вы пропустили PyImport_ImportModule при поиске вариантов?   -  person user2357112 supports Monica    schedule 25.03.2020
comment
да, но мой приоритет - не добавлять как можно больше зависимостей от 3-й части.   -  person Rika    schedule 25.03.2020
comment
@user2357112supportsMonica Я понял, но, к сожалению, не совсем понял   -  person Rika    schedule 25.03.2020
comment
PyObject *module = PyImport_ImportModule("packagename.submodulename");. То, что вы делаете, действительно странно и не дает желаемого эффекта - вы создаете новый объект модуля для несуществующего модуля, совершенно не связанного с тем, который вы хотите.   -  person user2357112 supports Monica    schedule 25.03.2020
comment
Кстати, я использую PyImport_AddModuleObject, а не PyImport_ImportModule. Я предположил, что когда я импортировал модуль с помощью PyRun_SimpleString, я могу получить его дескриптор с помощью PyImport_AddModuleObject. по крайней мере, это то, что понял из документов!   -  person Rika    schedule 25.03.2020
comment
о, теперь я понял! большое спасибо!   -  person Rika    schedule 25.03.2020


Ответы (1)


Как указано в комментариях, моя первоначальная попытка импорта модуля совершенно неверна, и вместо этого я должен был сделать это:

auto module = PyImport_ImportModule("Package1.Module1");

поэтому я сделал так:

auto module = PyImport_ImportModule("FV.F_V");

После этого я получаю гораздо более значимый вывод, как вы можете видеть:

module: 0000021306FF9B38
size: 30
FaceVerification: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
Image: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
Path: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__builtins__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__cached__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__doc__: FV.F_V
__file__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\F_V.py
__loader__: FV
__name__: FV.F_V
__package__: FV
__spec__: FV
__warningregistry__ : C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
align_face: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
cv2: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
data_transforms: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
get_central_face_attributes: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
math: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
nn: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
np: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
os: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
pickle: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
plt: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet101: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet18: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet50: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
scipy: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
time: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
torch: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
tqdm: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
transforms : C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc

person Rika    schedule 25.03.2020