0

I'm trying to import a module in C++; the module resides in a package and should be accessed like:

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

I'm on Python 3.6 and for this version what I have found so far is to use PyRun_SimpleString to do the import and then use PyImport_AddModuleObject to have a handle to my module. that is:

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

so that down the road I can access its different attributes, something like this:

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;

When I try to run this code, I get this output which shows the maps contents:

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

So this is the result of PyModule_GetDict(module); However, when it comes to the class extraction from this module, it fails, that is, the PyDict_GetItemString(pdict, "MyClass1"); returns null.

It seems to me the module handler itself is not right and that is probably because maybe it doesn't point to the actual module which means I completely failed at importing and getting a handle to that module.

Therefore I can't think of any other way that allows me to import a module and use it like this.

What am I missing here?

7
  • Have you considered using a C++ framework for embedding Python? For example Boost Python (or others)? Such frameworks usually makes it easier. Commented Mar 25, 2020 at 4:10
  • Did you overlook PyImport_ImportModule while searching for options? Commented Mar 25, 2020 at 4:12
  • yes, but my priority is not to add any 3rd part dependency as much as possible. Commented Mar 25, 2020 at 4:14
  • @user2357112supportsMonica I did, but unfortunately really didn't understand it Commented Mar 25, 2020 at 4:15
  • 2
    PyObject *module = PyImport_ImportModule("packagename.submodulename");. What you're doing is really weird and doesn't have the effect you want - you're creating a new module object for a nonexistent module completely unrelated to the one you want. Commented Mar 25, 2020 at 4:26

1 Answer 1

0

As pointed in the comments, my initial attempt for importing the module is completely wrong, and instead I should have done this :

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

so I did so :

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

After doing this, now I get much more meaningful output as you can see:

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.