Оболочка вызывающей функции C ++ с использованием расширения типов пакетов variadic
Я изучил множество шаблонов с расширением пакета variadic, но все же не могу собрать все статьи, которые нашел здесь, чтобы достичь своей цели. Пожалуйста, примите мои извинения за то, что, возможно, излишним. Я связан с некоторыми API, и я связан с некоторыми сигнатурами функций, как здесь:
static bool WrapperFunction(JSContext *cx, unsigned argc, JS::Value *vp)
Я пытаюсь обернуть объекты и функции для использования в JavaScript под SpiderMonkey. Чтобы интегрировать некоторый C API, должны быть реализованы оболочки для данных объекта и методы оболочки для некоторого объекта.
Мое решение привело меня к следующей логике оболочки, чтобы можно было вызывать методы с несколькими аргументами, но я не знаю, как этого добиться:
template<typename jsType, typename jsReturnType, typename MethodType, MethodType Method, typename... jsParamType>
static bool VAMethodRet(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
jsReturnType::PrivateType result = jsReturnType::PrivateTypeDefaultValue();
Здесь начинаются мои проблемы.
Первый шаг. Разверните ... jsParamType ... pack с вызовом метода для каждого jsParamType, чтобы создать экземпляр объекта класса-оболочки для сопоставления соответствующего аргумента из аргументов, чтобы подготовить вызов функции API C.
Другими словами, jsParamType сообщает тип, который он переносит, чтобы он мог извлечь объект типа C для каждого параметра, передаваемого в функцию C API.
Первый jsParamType соответствует args [0], второй jsParamType соответствует args1 и т.д., до последнего jsParamType, который соответствует args [argc].
Можно получить меньше элементов в аргументах, чем sizeof ... jsParamType, в этом случае базовый объект C должен быть инициализирован со значением по умолчанию.
Мета-информация о параметрах или обертках объектов уже достигается статическими методами (например, jsParamType :: jsType :: PrivateTypeDefaultValue ()).
В конце концов, расширенный пакет должен быть массивом или вектором разнородных объектов.
Функция сопоставления должна быть шаблонной, основанной на jsParamType, но также получать индекс расширенного пакета переменных и локальную переменную args, чтобы получить правильный объект для анализа - вот моя первая проблема:
Как передать индекс в метод?
Я пытался получить вдохновение отсюда, но я не могу заставить его работать:Вызов функции для каждого аргумента шаблона переменной и массива
Второй шаг, После этого я планирую использовать подобную технику здесь:Получить индекс аргумента при распаковке списка аргументов с помощью шаблонов Variadic чтобы вызвать функцию API C с правильными аргументами - возможно ли это?
Третий шаг, В конце, на основе статической функции jsParamType, называемой IsOut (), значения out обновят содержимое локальной переменной args, но это следует сделать снова, используя новое расширение, аналогичное первому шагу, чтобы вернуть некоторые значения с использованием информации о типе, присутствующей в элементах jsParamType.
Последнее, что нужно сделать, это установить возвращаемое значение, что тривиально.
Условные обозначения:jsType является типом структуры, содержащей указатель на функции C API, так как они сгруппированы поставщиком C API.jsReturnType это тип возвращаемого значения. (просто для справки здесь ...)метод метод C API, который должен быть вызванMethodType тип.
Пожалуйста, помогите мне написать такой код, так как я не могу заставить его работать. Я не прошу думать за меня и быть моим частным программистом. У меня просто нет опыта работы с этой частью препроцессора, я вижу много примеров, много ошибок бросков, или я не могу их расширить, чтобы достичь вышеуказанной функции. Спасибо.
РЕДАКТИРОВАТЬ 1
Спасибо за ответ,AndyG, Вот более или менее псевдокод:
// *jsType* is a type of the struct containing the pointer to the C API functions, as these are grouped by the C API's provider.
// *jsReturnType* is the return type. (just for reference here...)
// *Method* is a C API method to be called, having the *MethodType* type.
// The non-template part of the function signature is needed untouched by SpiderMonkey
template<typename jsType, typename jsReturnType, typename MethodType, MethodType Method, typename... jsParamType>
static bool VAMethodRet(JSContext *cx, unsigned argc, JS::Value *vp)
{
// get the collection of passed arguments (SpiderMonkey stuff), in args, each element accessible by index
// argc is the number of parameters passed from javascript
WrappersCollection args = GetCallArgsFromVp(argc, vp);
jsReturnType::PrivateType result = jsReturnType::PrivateTypeDefaultValue(); // creates an instance of a return value wrapper to receive the return value later
// 1. Match wrappers in the WrappersCollection against their types in order to get their C type values
CDataCollection cdata = array or vector of heterogeneous objects (int, char*, structs etc.);
for each (jsParamType in the variadic pack ...)
{
cdata[jsParamTypeIndex] = Match<jsParamType, jsParamTypeIndex>(args);
}
// the above should be done by expanding the pack somehow
// with emphasis on checking if argc[jsParamTypeIndex] was passed actually, because it's possible to have jsParamTypeIndex > argc
// I don't know how to do it otherwise, by matching some param types variadic pack against a variadic pack of data arguments with different number of elements
// 2. Transform the cdata collection into a variadic parameters pack in order to pass them to the C function.
// The amount of args is specified by the function
result = CFunction(cdata...);
// 3. Update returned data in *out* params in the collection of wrapper objects received in the first place
// index of the param in pack is necessary again
// due to the different number of elements in the param types variadic pack versus the variadic pack of data arguments
for each (jsParamType in the variadic pack ...)
{
if (jsParamType::IsOUT())
{
cdata[jsParamTypeIndex] = MatchBack<jsParamType, jsParamTypeIndex>(args);
}
}
// the rest of things to do
MatchReturnValue(result);
return true; // SpiderMonkey needs to know the success of the operation
}
Это более понятно?