У меня проблема, и мне нужна помощь в поиске решения.
Что я сейчас делаю
Я пытаюсь использовать PyBind11 для отправки нескольких переменных из C ++ в Python (который затем используется для записи данных sql, но это не главное). Я должен сделать это, используя следующий процесс:
SQL_Service.cpp:
namespace py = pybind11;
PYBIND11_PLUGIN(sqlserv)
{
py::module m("sqlserv", "pybind11 sql plugin");
m.attr("bet_player") = BET_PLAYER;
m.attr("total_winnings") = TOTAL_WINNINGS;
return m.ptr();
}
py::object import(const std::string& module, const std::string& path, py::object& globals)
{
py::dict locals;
locals["module_name"] = py::cast(module);
locals["path"] = py::cast(path);
py::eval<py::eval_statements>(
"import imp\n""new_module = imp.load_module(module_name, open(path), path, ('py', 'U', imp.PY_SOURCE))\n",
globals,
locals);
return locals["new_module"];
}
int SQL_Service::Log_SQL()
{
try
{
Py_Initialize();
pybind11_init();
py::object main = py::module::import("__main__");
py::object globals = main.attr("__dict__");
py::object module = import("sqlserv", "py_sql_service.py", globals); //name of the python file used
return 0;
}
catch (const py::error_already_set&)
{
std::cerr << ">>> Error! Uncaught exception:\n";
PyErr_Print();
return 1;
}
}
Это все хорошо, и я могу вставить эти две переменные (bet_player и total_winnings) в python и обработать их.
Я хотел бы создать еще один «PYBIND11_PLUGIN (что-то другое)», который связан с использованием разных переменных и связан с другим скриптом Python.
Проблемы возникают, когда я пытаюсь определить другой PYBIND11_PLUGIN. А именно:
namespace py = pybind11;
PYBIND11_PLUGIN(sqlserv)
{
py::module m("sqlserv", "pybind11 sql plugin");
m.attr("bet_player") = BET_PLAYER;
m.attr("total_winnings") = TOTAL_WINNINGS;
return m.ptr();
}
PYBIND11_PLUGIN(somethingelse)
{
py::module m("somethingelse", "pybind11 sql plugin");
m.attr("bet_player2") = BET_PLAYER2;
m.attr("total_winning2s") = TOTAL_WINNINGS2;
return m.ptr();
}//This gives me the following error
Error C2084 function 'PyObject *pybind11_init(void)' already has a body
Чего я надеюсь достичь
Я хочу использовать свой класс (SQL_Service) для определения различных функций, которые будут получать данные из других частей моей программы для упаковки и отправки в различные сценарии Python, каждый из которых получает только те данные, которые ему необходимы. (См. Process_Baccarat (…) {…} в моем полном примере ниже).
Что меня сбивает с толку
Я опирался на различные учебные пособия, которые дают небольшие фрагменты кода или демонстрируют немного разные способы работы с PyBind. Таким образом, я не знаю, как получить именно то, что я ищу.
Я не уверен, что это пространства имен, или, может быть, я просто не могу иметь 2 из этих функций. Возможно, есть другой способ решения этой проблемы полностью, который был бы лучше.
Я также не слишком рад тому, что мне нужно использовать глобальные переменные (опять же, у меня возникло некоторое замешательство в пространстве имен), поэтому, если есть способ, которым все это можно было бы красиво обернуть, это то, что я ищу. Рабочий пример кода будет принята с благодарностью.
Вот мой полный (рабочий) файл SQL_Service.cpp для справки:
#include "SQL_Service.hpp"
#include "Pybind\include\pybind11\pybind11.h"#include "Pybind\include\pybind11\eval.h"
#include <string>
#include <iostream>//G_VARS
int BET_PLAYER = 0;
int TOTAL_WINNINGS = 0;SQL_Service::SQL_Service()
{
}
SQL_Service::~SQL_Service()
{
}
namespace py = pybind11;
PYBIND11_PLUGIN(sqlserv)
{
py::module m("sqlserv", "pybind11 sql plugin");
m.attr("bet_player") = BET_PLAYER;
m.attr("total_winnings") = TOTAL_WINNINGS;
return m.ptr();
}py::object import(const std::string& module, const std::string& path, py::object& globals)
{
py::dict locals;
locals["module_name"] = py::cast(module);
locals["path"] = py::cast(path);
py::eval<py::eval_statements>(
"import imp\n""new_module = imp.load_module(module_name, open(path), path, ('py', 'U', imp.PY_SOURCE))\n",
globals,
locals);
return locals["new_module"];
}
//I Want to make all sorts of different kinds of these functions.
void SQL_Service::Process_Baccarat(int bet_player, int total_winnings)
{
BET_PLAYER = bet_player;
TOTAL_WINNINGS = total_winnings;
Log_SQL();
}
//And more of these too, if needed.
int SQL_Service::Log_SQL()
{
try
{
Py_Initialize();
pybind11_init();
py::object main = py::module::import("__main__");
py::object globals = main.attr("__dict__");
py::object module = import("sqlserv", "py_sql_service.py", globals); //name of the python file used
return 0;
}
catch (const py::error_already_set&)
{
std::cerr << ">>> Error! Uncaught exception:\n";
PyErr_Print();
return 1;
}
}
Вам нужно поставить PYBIND11_PLUGIN
в отдельных сборниках. В вашем случае это будет означать разделение вашего кода между: sqlserv.cpp
а также somethingelse.cpp
,
Однако я не уверен, что это лучшее решение вообще. Может быть, разные классы со статическими членами в одном модуле?
Других решений пока нет …