【问题标题】:PyImport_ImportModule, possible to load module from memory?PyImport_ImportModule,可以从内存中加载模块吗?
【发布时间】:2016-10-03 00:03:49
【问题描述】:

我在我的 C++ 程序中嵌入了 python。

我使用 PyImport_ImportModule 加载我写在 .py 文件中的模块。 但是我怎样才能从内存中加载它呢?假设我的 .py 文件是加密的,所以我需要先解密它并将代码提供给 python 执行。

此外,如果我可以绕过/拦截或修改导入机制,那就太好了,这样就不会从文件系统加载模块,而是从我自己的内存块加载,我该如何/可以这样做?

【问题讨论】:

    标签: python c++ cpython python-embedding


    【解决方案1】:

    以下示例显示如何从 C 字符串定义模块:

    #include <stdio.h>
    #include <Python.h>
    int main(int argc, char *argv[])
    {
        Py_Initialize();
        PyRun_SimpleString("print('hello from python')");
    
        // fake module
        char *source = "__version__ = '2.0'";
        char *filename = "test_module.py";
    
        // perform module load
        PyObject *builtins = PyEval_GetBuiltins();
        PyObject *compile = PyDict_GetItemString(builtins, "compile");
        PyObject *code = PyObject_CallFunction(compile, "sss", source, filename, "exec");
        PyObject *module = PyImport_ExecCodeModule("test_module", code);
    
        PyRun_SimpleString("import test_module; print(test_module.__version__)");
    
        Py_Finalize();
        return 0;
    }
    

    输出:

    hello from python
    version: 2.0
    

    您可以在文档中了解import hooks。您将需要使用find_moduleload_module 方法定义一个类。像下面这样的东西应该可以工作:

    PyObject* find_module(PyObject* self, PyObject* args) {
        // ... lookup args in available special modules ...
        return Py_BuildValue("B", found);
    }
    
    PyObject* load_module(PyObject* self, PyObject* args) {
        // ... convert args into filname, source ...
        PyObject *builtins = PyEval_GetBuiltins();
        PyObject *compile = PyDict_GetItemString(builtins, "compile");
        PyObject *code = PyObject_CallFunction(compile, "sss", source, filename, "exec");
        PyObject *module = PyImport_ExecCodeModule("test_module", code);
        return Py_BuildValue("O", module);
    }
    
    static struct PyMethodDef methods[] = {
        { "find_module", find_module, METH_VARARGS, "Returns module_loader if this is an encrypted module"},
        { "load_module", load_module, METH_VARARGS, "Load an encrypted module" },
        { NULL, NULL, 0, NULL }
    };
    
    static struct PyModuleDef modDef = {
        PyModuleDef_HEAD_INIT, "embedded", NULL, -1, methods, 
        NULL, NULL, NULL, NULL
    };
    
    static PyObject* PyInit_embedded(void)
    {
        return PyModule_Create(&modDef);
    }
    
    int main() {
        ...
        PyImport_AppendInittab("embedded", &PyInit_embedded);
        PyRun_SimpleString("\
    import embedded, sys\n\
    class Importer:\n\
        def find_module(self, fullpath):\n\
            return self if embedded.find_module(fullpath) else None\n\
        def load_module(self, fullpath):\n\
            return embedded.load_module(fullpath)\n\
    sys.path_hooks.insert(0, Importer())\n\
    ");
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 1970-01-01
      • 2015-07-02
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多