如何在同一实例中成功地从 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 文件。
嘿,所以我试图在 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 文件。