如何在同一实例中成功地从 C++ 调用 Python 函数?

How can i call a Python Function from C++ in the same instance succesfully?

嘿,所以我试图在 C++ 中嵌入 Python Selenium,但我成功地打开了浏览器并获得了一个项目。我怎样才能成功打开浏览器并在 google 搜索栏中搜索 HELLO?

#define PY_SSIZE_T_CLEAN
#include <python/Python.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <filesystem>
#include <python/pyhelper.hpp>


using namespace std;
#define PYSRCDIR "/PythonSrc/"

PyObject* pName, * pModule, * pFunc;
PyObject* pArgs, * pValue;


inline int  __initialize_path(string __file) {
    file = __file;
    
    std::filesystem::path path = std::filesystem::current_path();
    std::string _path = path.string();
  
    std::replace(_path.begin(), _path.end(), '\', '/');
    try {
        PyRun_SimpleString("import sys");
    }
    catch (...) {
        cout << "cpp >> INITIALIZE with <Py_Initialize();> first\n";
        return -1;
    }
    PyRun_SimpleString((string("sys.path.append(\"") + _path + string(PYSRCDIR) + string("\")")).c_str());
    
    pName = PyUnicode_DecodeFSDefault(file.c_str());
    /* Error checking of pName left out */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    return 0;
}
/**
 * It calls a python function from C++
 * 
 * @param file The name of the python file to be executed. It should be located in PYSRCDIR dir
 * @param funcptr The name of the function to call.
 * 
 * @return The return value is the status.
 */
inline int __callpy_noarg(string funcptr) {
   
    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, funcptr.c_str());
        /* pFunc is a new reference */

        if (pFunc && PyCallable_Check(pFunc)) {
            pValue = PyObject_CallObject(pFunc , NULL);
        }
        else {
            /* Checking if there is an error. If there is an error, it prints it out. */
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", funcptr);
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", file.c_str());
        return 1;
    }
    
    return 0;
}
 /**
  * It calls a Python function with args from C++.
  * 
  * @param file The name of the python file to be executed.
  * @param funcptr The name of the function to call.
  * @param args A vector of strings that are the arguments to pass to the Python function.
  * 
  * @return The return value is the status.
  */
inline int __callpy_warg(string funcptr, vector<string>* args) {
     
     if (pModule != NULL) {
         pFunc = PyObject_GetAttrString(pModule, funcptr.c_str());
         /* pFunc is a new reference */

         if (pFunc && PyCallable_Check(pFunc)) {
             pArgs = PyTuple_New(args->size());
             for (i = 0; i < args->size(); ++i) {
                 string str = args->at(i);
                 pValue = PyUnicode_FromString(str.c_str());
                 if (!pValue) {
                     Py_DECREF(pArgs);
                     Py_DECREF(pModule);
                     fprintf(stderr, "Cannot convert argument\n");
                     return 1;
                 }
                 /* pValue reference stolen here: */
                 PyTuple_SetItem(pArgs, i, pValue);
             }
             pValue = PyObject_CallObject(pFunc, pArgs);
             Py_DECREF(pArgs);
             if (pValue != NULL) {
                 printf("Result of call: %ld\n", PyLong_AsLong(pValue));
                 Py_DECREF(pValue);
             }
             else {
                 Py_DECREF(pFunc);
                 Py_DECREF(pModule);
                 PyErr_Print();
                 fprintf(stderr, "Call failed\n");
                 return 1;
             }
         }
         else {
             if (PyErr_Occurred())
                 PyErr_Print();
             fprintf(stderr, "Cannot find function \"%s\"\n", funcptr.c_str());
         }
         Py_XDECREF(pFunc);
         Py_DECREF(pModule);
     }
     else {
         PyErr_Print();
         fprintf(stderr, "Failed to load \"%s\"\n", file.c_str());
         return 1;
     }
     
     return 0;
 }


int main()
{
    CPyInstance inst;

    __initialize_path("pyemb3");
    std::vector<string>* vec1 = new std::vector<string>;
    vec1->push_back(" ");
    __callpy_warg("init_selenium", vec1);
    delete vec1;

    std::vector<string>* vec2 = new std::vector<string>;
    vec2->push_back("https://www.google.com/");
    __callpy_warg("get_search", vec2);
    delete vec2;

    std::vector<string>* vec3 = new std::vector<string>;
    vec3->push_back("q");
    __callpy_warg("get_elem_NAME", vec3);
    delete vec3;

    std::vector<string>* vec4 = new std::vector<string>;
    vec4->push_back("0");
    __callpy_warg("click_ELEMENT", vec4);
    delete vec4;


    std::vector<string>* vec5 = new std::vector<string>;
    vec5->push_back("0");
    vec5->push_back("HELLO");
    __callpy_warg("type_ELEMENT", vec5);
    delete vec5;

    std::vector<string>* vec6 = new std::vector<string>;
    vec6->push_back("0");
    vec6->push_back('\ue007');// enter key unicode
    __callpy_warg("type_ELEMENT", vec6);
    delete vec6;



   
}

所以在主函数中我调用了这个 python 文件中定义的一些函数

# It imports the necessary modules to run the code.

from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import threading
import chromedriver_autoinstaller

chromedriver_autoinstaller.install()

global option
driver = ""
elements_list = []




def init_selenium(param):
    options = Options()
    if not param == "":
        paramlist = param.split(" ");
    else:
        print("init_selenium --NO ARGS")
    if "headless" in paramlist:
        options.add_argument("--headless")
        print("init_selenium --HEADLESS")

    global driver;
    driver = webdriver.Chrome(options=options)


def get_search(PATH):
    global driver;
    if not PATH == "":
        driver.get(PATH)
    else:
        print("get_search --NO PATH SPECIFIED")


def wait_elem_XPATH(ELEMDATA , TIME):
    global driver;
    try:
        element1 = WebDriverWait(driver, int(TIME)).until(
            EC.presence_of_element_located((By.XPATH, ELEMDATA)))
    except:
        print("wait_elem_XPATH --INVALID ARGS")

def get_elem_XPATH(ELEMDATA):
    global driver;
    element3 = driver.find_element_by_xpath(ELEMDATA)
    global elements_list;
    elements_list.append(element3);


def get_elem_NAME(ELEMDATA):
    global driver;
    element3 = driver.find_element_by_name(ELEMDATA)
    global elements_list;
    elements_list.append(element3);

def click_ELEMENT(ELEMNUMBER):
    global elements_list;
    elements_list[int(ELEMNUMBER)].click()

def type_ELEMENT(ELEMNUMBER , TEXT):
    global elements_list;
    elements_list[int(ELEMNUMBER)].send_keys(TEXT)

def driver_QUIT():
    global driver;
    driver.quit()


def driver_WAIT(sec):
    driver.implicitly_wait(int(sec)) # seconds

错误说它找不到函数,但可以找到其他函数....

AttributeError: '_collections._deque_iterator' object has no attribute 'click_ELEMENT'
Cannot find function "click_ELEMENT"
AttributeError: 'builtin_function_or_method' object has no attribute 'type_ELEMENT'
Cannot find function "type_ELEMENT"
AttributeError: 'AttributeError' object has no attribute 'type_ELEMENT'
Cannot find function "type_ELEMENT"

github 项目 link : https://github.com/Vasika-uso/Selenium-embedded-in-cpp

我想你可以制作一个 .dll 形式的 .py 文件并在编译你的 C++ 代码时传递它。 您可以使用 pyinstaller 将 .py 文件转换为可执行文件,并将所有必需的包转换为 .dll 格式。

第一步.pip安装pyinstaller,

第 2 步。新建 python 文件,我们将其命名为 code.py .

第 3 步。编写一些代码行,即 print("Hello World")

步骤 4. 在同一位置打开命令提示符并输入 pyinstaller code.py 按回车键。最后一步看到在同一个位置有两个文件夹名称build,dist 将被创建。 dist 文件夹内有文件夹代码,该文件夹内有一个 exe 文件 code.exe 以及所需的 .dll 文件。