Я пытаюсь разоблачить шаблонные функции C ++ в JavaScript, используя QTE QWebengineView и QWebChannel . Цель состоит в том, чтобы включить динамический вызов функций C ++ из JavaScript, с различными типами аргументов и возвратными значениями.
Проблемы
Преобразование аргумента
Я использую рекурсивный шаблон (convert_args) для преобразования аргументов из Qvariantlist в типы C ++. Тем не менее, я не уверен, правильно ли этот подход обрабатывает ссылки и различные типы аргументов, особенно при работе со сложными или нетривиальными типами данных. > После преобразования аргументов в правильные типы я сталкиваюсь с проблемами с вызовом функции, используя std :: invoke . Типы, по -видимому, несоответствия или ссылки обрабатываются неправильно при распаковке аргументов из кортежа. и неполные типы во время компиляции. В частности, я сталкиваюсь с проблемами при вызове функции с аргументами, распакованными из std :: tuple из -за несовместимости типа.
Что я попробовал
использовал рекурсивный шаблон (convert_args) в преобразование QvariantList в std :: tuple с ожидаемыми типами аргументов.
anpilized std :: invoke для вызова шаблонной функции C ++, передавая функцию. Раскрытые аргументы из корпуса.
обработанные ссылки с использованием std :: remove_reference_t < /code> для учета ссылок на типы в аргументах.
Несмотря на это Попытки, проблема сохраняется. Функция должна выполняться правильно с соответствующими типами аргументов и возвращать ожидаемое значение. < /P>
#include
#include
#include
#include
#include
#include
#include
template
struct function_traits : function_traits {};
template
struct function_traits
{
using return_type = R;
using arg_types = std::tuple;
using signature_t = R(Args...);
static constexpr size_t arity = sizeof...(Args);
template
using arg = typename std::tuple_element::type;
};
template
struct function_traits
{
using return_type = R;
using arg_types = std::tuple;
using signature_t = R(Args...);
static constexpr size_t arity = sizeof...(Args);
template
using arg = typename std::tuple_element::type;
};
template
struct function_traits
{
using return_type = ReturnType;
using arg_types = std::tuple;
using signature_t = ReturnType(Args...);
static constexpr size_t arity = sizeof...(Args);
template
using arg = typename std::tuple_element::type;
};
template
struct function_traits
{
using return_type = ReturnType;
using arg_types = std::tuple;
using signature_t = ReturnType(Args...);
static constexpr size_t arity = sizeof...(Args);
template
using arg = typename std::tuple_element::type;
};
template
struct function_traits
{
using return_type = ReturnType;
using arg_types = std::tuple;
using signature_t = ReturnType(Args...);
static constexpr size_t arity = sizeof...(Args);
template
using arg = typename std::tuple_element::type;
};
template
struct function_traits
{
using return_type = ReturnType;
using arg_types = std::tuple;
using signature_t = ReturnType(Args...);
static constexpr size_t arity = sizeof...(Args);
template
using arg = typename std::tuple_element::type;
};
template
struct function_traits
{
using return_type = ReturnType;
using arg_types = std::tuple;
using signature_t = ReturnType(BoundArgs...);
static constexpr size_t arity = sizeof...(BoundArgs);
template
using arg = typename std::tuple_element::type;
};
template
using function_signature_t = typename function_traits::signature_t;
class Invoker : public QObject {
Q_OBJECT
public:
using callback_t = std::function;
explicit Invoker(QObject* parent = nullptr) : QObject(parent) {}
void add(const QString& name, const callback_t& callback) {
m_functions[name] = std::move(callback);
}
Q_INVOKABLE QVariant call(const QString& name, const QVariantList& args) {
return m_functions[name](std::move(args));
}
Q_INVOKABLE void debug(const QString& message) {
qDebug().noquote() resize(800, 600);
channel->registerObject("invoker", &invoker);
view->page()->setWebChannel(channel);
view->setUrl(QUrl::fromLocalFile(""));
}
MainWindow::~MainWindow() {
delete view;
delete channel;
}
template
T convert_variant(const QVariant& var) {
return var.value();
}
template
auto convert_args(const QVariantList& args) {
if constexpr (Index < sizeof...(ArgTypes)) {
return std::tuple_cat(
std::make_tuple(convert_variant(args.at(Index))),
convert_args(args)
);
} else {
return std::tuple{};
}
}
template
decltype(auto) call_function_impl(Function&& function, Tuple&& tuple, std::index_sequence) {
return std::invoke(std::forward(function),
std::forward(std::get(std::forward(tuple)))...);
}
template
decltype(auto) call_function(Function&& function, Tuple&& tuple) {
return call_function_impl(
std::forward(function),
std::forward(tuple),
std::make_index_sequence{}
);
}
template
void MainWindow::expose(const std::string& name, Function&& function) {
using argument_types = typename function_traits::arg_types;
using return_type = typename function_traits::return_type;
invoker.add(QString::fromStdString(name),
[function = std::forward(function)](const QVariantList& args) -> QVariant {
constexpr size_t arity = webflex::utils::function_traits::arity;
if (args.size() == arity) {
auto typed_args = convert_args(args);
return call_function(function, typed_args);
}
return QVariant();
});
}
void function(int, QString) {}
int main(int argc, char** argv) {
QApplication a(argc, argv);
MainWindow w;
w.expose("add", [](int x, int y) {
return x + y;
});
w.show();
return a.exec();
}
#include "main.moc"
< /code>
Сообщения об ошибках < /p>
ошибки компиляции, связанные с типами несоответствующих аргументов и неполными типами во время вызова функции. < /p>
`
In file included from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtCore/qtypeinfo.h:13,
from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtCore/qglobal.h:47,
from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtGui/qtguiglobal.h:7,
from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtWidgets/qtwidgetsglobal.h:7,
from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtWidgets/qmainwindow.h:7,
from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtWidgets/QMainWindow:1,
from /home/hacker-pro/Projects/TestPrfoject/main.cpp:1:
/usr/include/c++/13/tuple: In instantiation of ‘constexpr decltype(auto) std::__apply_impl(_Fn&&, _Tuple&&, index_sequence) [with _Fn = const main(int, char**)::&; _Tuple = tuple&; long unsigned int ..._Idx = {0}; index_sequence = integer_sequence]’:
/usr/include/c++/13/tuple
/home/hacker-pro/Projects/TestPrfoject/main.cpp:93:22: required from ‘decltype(auto) call_function_impl(Function&&, Tuple&&, std::index_sequence) [with Function = const main(int, char**)::&; Tuple = std::tuple&; long unsigned int ...I = {0}; std::index_sequence = std::integer_sequence]’
/home/hacker-pro/Projects/TestPrfoject/main.cpp:98:30: required from ‘decltype(auto) call_function(Function&&, Tuple&&) [with Function = const main(int, char**)::&; Tuple = std::tuple&]’
/home/hacker-pro/Projects/TestPrfoject/main.cpp:123:29: required from ‘void MainWindow::expose(const std::string&, Function&&) [with Function = main(int, char**)::; std::string = std::__cxx11::basic_string]’
/home/hacker-pro/Projects/TestPrfoject/main.cpp:135:13: required from here
/usr/include/c++/13/tuple
2288 | return std::__invoke(std::forward(__f),
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
2289 | std::get(std::forward(__t))...);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/13/variant:41,
from /home/hacker-pro/Qt/6.7.3/gcc_64/include/QtCore/qtypeinfo.h:11:
/usr/include/c++/13/bits/invoke.h:90:5: note: candidate: ‘template constexpr typename std::__invoke_result::type std::__invoke(_Callable&&, _Args&& ...)’
90 | __invoke(_Callable&& __fn, _Args&&... __args)
| ^~~~~~~~
/usr/include/c++/13/bits/invoke.h:90:5: note: template argument deduction/substitution failed:
/usr/include/c++/13/bits/invoke.h: In substitution of ‘template constexpr typename std::__invoke_result::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = const main(int, char**)::&; _Args = {std::tuple&}]’:
/usr/include/c++/13/tuple
/usr/include/c++/13/tuple
/home/hacker-pro/Projects/TestPrfoject/main.cpp:93:22: required from ‘decltype(auto) call_function_impl(Function&&, Tuple&&, std::index_sequence) [with Function = const main(int, char**)::&; Tuple = std::tuple&; long unsigned int ...I = {0}; std::index_sequence = std::integer_sequence]’
/home/hacker-pro/Projects/TestPrfoject/main.cpp:98:30: required from ‘decltype(auto) call_function(Function&&, Tuple&&) [with Function = const main(int, char**)::&; Tuple = std::tuple&]’
/home/hacker-pro/Projects/TestPrfoject/main.cpp:123:29: required from ‘void MainWindow::expose(const std::string&, Function&&) [with Function = main(int, char**)::; std::string = std::__cxx11::basic_string]’
/home/hacker-pro/Projects/TestPrfoject/main.cpp:135:13: required from here
/usr/include/c++/13/bits/invoke.h:90:5: error: no type named ‘type’ in ‘struct std::__invoke_result’
make[2]: *** [CMakeFiles/main.dir/build.make:93: CMakeFiles/main.dir/main.cpp.o] Ошибка 1
make[1]: *** [CMakeFiles/Makefile2:110: CMakeFiles/main.dir/all] Ошибка 2
make: *** [Makefile:136: all] Ошибка 2
`
Подробнее здесь: https://stackoverflow.com/questions/794 ... h-qvariant