C + + Call Python3

Source: Internet
Author: User
Tags garbage collection goto python script

As a glue language, Python can easily invoke C, C + + and other languages, and can also invoke Python's modules in other languages.

Python provides a C + + library that makes it easy for developers to invoke Python modules from C + + programs.

Specific operation can be consulted: official documents

The following steps are required when invoking a Python module:

    1. Initializing the python calling environment
    2. Loading the corresponding Python module
    3. Load the corresponding Python function
    4. Convert a parameter to a Python tuple type
    5. Calling a Python function and passing in a parameter tuple
    6. Get return value
    7. Parse the return value based on the definition of the Python function
Initialization

When calling the Python module, you need to include the Python.h header file, which is typically included in the include file in the installed Python directory, where you first need to add the path to the project

May hold an error after the inclusion is complete: not found Inttypes.h file, in an error on the Windows platform is very common, if you report this error, you need to download the corresponding Inttypes.h file on the internet and then put into the corresponding directory, I put it in the VC's include directory

may also hold an error after the inclusion of these files, not found python36_d.lib in the Python environment do not find this file, This time can modify the Pyconfig.h file, the Lib changed to Python36.lib, specific operation please refer to this link: 78947526

It is also important to note that the download of the Python environment must be the same type as the target program, such as when you create a new Win32 project in VS, you need to refer to the 32-bit version of Python when referencing the python environment

After these preparations are done, call the Py_initialize function to initialize the Python environment before calling Python, and then we can call py_isinitialized to detect if the Python environment is initialized successfully
Here is an example of initializing a Python environment

BOOL Init(){    Py_Initialize();    return Py_IsInitialized();}
Calling the Python module

Invoking a Python module makes it easy to invoke a Python statement or call a function in a Python module.

Simple invocation of Python statements

For a simple Python statement (as in the case of a statement we entered in a Python interactive environment), you can invoke the function directly, which PyRun_SimpleString requires the ANSI string of a Python statement as a parameter that returns the value of type int. If 0 means execution succeeds or fails

void ChangePyWorkPath(LPCTSTR lpWorkPath){    TCHAR szWorkPath[MAX_PATH + 64] = _T("");    StringCchCopy(szWorkPath, MAX_PATH + 64, _T("sys.path.append(\""));    StringCchCat(szWorkPath, MAX_PATH + 64, lpWorkPath);    StringCchCat(szWorkPath, MAX_PATH + 64, _T("\")"));    PyRun_SimpleString("import sys");    USES_CONVERSION;    int nRet = PyRun_SimpleString(T2A(szWorkPath));    if (nRet != 0)    {        return;    }}

This function is mainly used to add the incoming path to the current Python execution environment, so that it can be easily imported into our custom module
The function first organizes a string of "sys.path.append (' path ')" In the form of string concatenation, where path is the parameter we pass in, and then calls Pyrun_simplestring to execute the "import sys" of Python. Statement to import the SYS module and then execute the previously stitched statement to add the corresponding path to the Python environment

Calling functions in a Python module

Calling a function in a Python module requires performing the 2~7 steps described earlier

    1. Load Python module (custom module)

The module that loads Python needs to call PyImport_ImportModule This function to pass in the name of a module as a parameter, note: This needs to pass in the name of the module, which is the name of the py file, and cannot take the. py suffix.

This function returns a pointer to a Python object, represented as Pyobject in C + +. This returns the object pointer of the module

    1. The function is then called PyObject_GetAttrString to load the method in the corresponding Python module, which requires two parameters, the first is a pointer to the corresponding module previously obtained, and the second parameter is the ANSI string for the function name. This function returns a pointer to the object that corresponds to the Python function. You need to use this pointer to call the Python function later.

After getting the pointer to the function we can call PyCallable_Check to detect if the corresponding object can be called, and if it can be called this function returns true otherwise false

    1. Then the parameters are passed in, and the parameters of the function in Python are passed in as tuples, so it is necessary to convert the passed arguments into tuples, and then call the PyObject_CallObject function to execute the corresponding Python function. This function requires two parameters the first is a pointer to the Python function object above, and the second parameter is a tuple that needs to pass in the parameters in the Python function. The function returns the Python tuple object, which is the return value of the Python function.
    2. After getting the return value is the parse parameter, we can use the corresponding function to convert the Python tuple into a variable in C + +
    3. Finally, a call is required Py_DECREF to dismiss the Python object's reference so that the Python garbage collector can properly reclaim the memory of those objects

The following is an example of an incoming NULL parameter

void Getmoduleinformation (in LPCTSTR-lppyfilename, out-LPTSTR lpvulname, out-long& level) {uses_conversion; Pyobject *pmodule = Pyimport_importmodule (T2A (lppyfilename));        Load Module if (NULL = = Pmodule) {g_outputstring (_t ("Load module [%s] failed"), lppyfilename);    Goto __clean_up; } pyobject *pgetinformationfunc = pyobject_getattrstring (Pmodule, "getinformation"); Load the function in the module if (NULL = = Pgetinformationfunc | |!        Pycallable_check (Pgetinformationfunc)) {g_outputstring (_t ("Load function [%s] failed"), _t ("getinformation"));    Goto __clean_up;    } pyobject *pyresult = Pyobject_callobject (Pgetinformationfunc, NULL);        if (NULL! = Pyresult) {Pyobject *pvulnameobj = Pytuple_getitem (pyresult, 0);        Pyobject *pvullevelobj = Pytuple_getitem (Pyresult, 1);        Gets the name information of the vulnerability int nstrsize = 0;        LPTSTR pvulname = pyunicode_aswidecharstring (Pvulnameobj, &nstrsize);        StringCchCopy (Lpvulname, MAX_PATH, pvulname); Pymem_free (PvulnaME);        Risk level for vulnerability: Pylong_aslong (pvullevelobj);        Py_decref (Pvulnameobj);    Py_decref (Pvullevelobj);    }//de-reference the Python object for Python garbage collection __clean_up:py_decref (pmodule);    Py_decref (Pgetinformationfunc); Py_decref (Pyresult);}

In the example, a function called getinformation is called, and the function is defined as follows:

def getInformation():    return "测试脚本", 1

The following is a function call that needs to pass in a parameter

BOOL Callscanmethod (in Lppython_modules_data ppymodule, in Lpctstr Lpurl, in Lpctstr Lprequestmethod, out LPTSTR LpHasVulU    RL, int buffsize) {uses_conversion;    Load module pyobject* pmodule = Pyimport_importmodule (T2A (ppymodule->szmodulename));        if (NULL = = Pmodule) {g_outputstring (_t ("Load module [%s] failed!!!"), ppymodule->szmodulename);    return FALSE;    }//Load module Pyobject *pyscanmethod = pyobject_getattrstring (Pmodule, "Startscan"); if (NULL = = Pyscanmethod | |!        Pycallable_check (Pyscanmethod)) {py_decref (pmodule);        G_outputstring (_t ("Load function [%s] failed!!!"), _t ("Startscan"));    return FALSE;    }//Load parameter pyobject* PArgs = Py_buildvalue ("ss", T2A (Lpurl), T2A (Lprequestmethod));    Pyobject *pres = Pyobject_callobject (Pyscanmethod, PArgs);    Py_decref (PArgs);        if (NULL = = pRes) {g_outputstring (_t ("Call function [%s] failed!!!!"), _t ("Startscan"));    return FALSE;    }//If it is a tuple, then the Python script returns two parameters, proving that the vulnerability was found if (Pytuple_check (pRes)) {    pyobject* Phasvul = Pytuple_getitem (pRes, 0);        Long Bhasvul = Pylong_aslong (Phasvul);        Py_decref (Phasvul);            if (Bhasvul! = 0) {pyobject* Pyurl = Pytuple_getitem (pRes, 1);            int nSize = 0;            LPWStr pszurl = pyunicode_aswidecharstring (Pyurl, &nsize);            Py_decref (Pyurl);            StringCchCopy (Lphasvulurl, Buffsize, Pszurl);            Pymem_free (Pszurl);        return TRUE;    }} py_decref (PRes); return FALSE;}

The corresponding Python functions are as follows:

def startScan(url, method):    if(method == "GET"):        response = requests.get(url)    else:        response = requests.post(url)    if response.status_code == 200:        return True, url    else:        return False
Conversion of C + + data types to Python objects

One of the key elements of Python's combination with C + + is the conversion of C + + to Python data types, which provide a series of functions for this problem python.

The formats for these functions are pyxxx_asxxx or pyxxx_fromxxx, and generally with as is the conversion of Python objects into C + + data types, with the From is to convert C + + objects to Python, The XXX in front of the PY represents the data type in Python. For example, to convert a PyUnicode_AsWideCharString string in Python to a wide character in C + + and to convert a Pyunicode_FromWideChar C + + string into a string in Python. One thing to note here is that Python3 abolished the normal string in 2, which takes all the strings as Unicode, so when calling 3, you need to convert all the strings to Unicode rather than to string as before. Please refer to the official Python instructions for specific conversion types.

The conversion of basic data types is described above, in addition to some container-type data such as tuples, dictionaries, and so on. The following is mainly about the operation of tuples. Tuples are a more important operation, because the tuple is required to pass arguments when the function is called and needs to be parsed to get the values in the tuple.

    1. Create a Python tuple object

Creating a tuple object can be used PyTuple_New to create an object of a tuple that requires a parameter to represent the number of objects in the tuple.

Then you need to create the corresponding Python object, you can use the previously mentioned conversion functions to create a normal Python object, and then call PyTuple_SetItem to set the contents of the tuple data, the function requires three parameters, the tuple object is a pointer, the index in the tuple and the corresponding data

Example:
cpp PyObject* args = PyTuple_New(2); // 2个参数 PyObject* arg1 = PyInt_FromLong(4); // 参数一设为4 PyObject* arg2 = PyInt_FromLong(3); // 参数二设为3 PyTuple_SetItem(args, 0, arg1); PyTuple_SetItem(args, 1, arg2);

Or if the tuples are simple data types, you can PyObject* args = Py_BuildValue(4, 3); create tuples directly using this method

    1. Parsing tuples

The Python function returns a tuple that needs to be parsed in C + +, and we can use it PyTuple_GetItem to get the data members in the tuple, which returns a pointer to Pyobject, and then uses the corresponding conversion function to convert the Python object to a C + + data type.

PyObject *pVulNameObj = PyTuple_GetItem(PyResult, 0);PyObject *pVulLevelObj = PyTuple_GetItem(PyResult, 1);//获取漏洞的名称信息int nStrSize = 0;LPTSTR pVulName = PyUnicode_AsWideCharString(pVulNameObj, &nStrSize);StringCchCopy(lpVulName, MAX_PATH, pVulName);PyMem_Free(pVulName); //释放由PyUnicode_AsWideCharString分配出来的内存//获取漏洞的危险等级level = PyLong_AsLong(pVulLevelObj);//最后别忘了将Python对象解引用Py_DECREF(pVulNameObj);Py_DECREF(pVulLevelObj);Py_DECREF(PyResult);

The functions for specific data type operations in Python are generally preceded by a py, followed by the name of the specific data type, such as the Pytuple series functions of the operations tuple and the Pylist series functions of the action list, and then if you want to manipulate the corresponding data type simply go to the official website to search for the corresponding name.

These code examples are the code in a demo that I wrote earlier, and the demo is on GitHub: Pyscanner

C + + Call Python3

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.