@@ -556,8 +556,155 @@ value_base to_value_base(T &&arg)
556556 }
557557}
558558
559+ template <typename ... Args, auto ... Is>
560+ auto register_function_args_tuple (void *args[], std::index_sequence<Is...>)
561+ {
562+ return std::tuple{ metacall::value<Args>(args[Is]).to_value ()... };
563+ }
564+
565+ template <typename ... Args>
566+ auto register_function_args (void *args[])
567+ {
568+ return register_function_args_tuple<Args...>(args, std::make_index_sequence<sizeof ...(Args)>());
569+ }
570+
571+ template <typename Ret>
572+ int register_function (const char *name, Ret (*func)(void ), void **func_ptr)
573+ {
574+ auto invoke = [](size_t argc, void *[], void *data) -> void * {
575+ // Check for correct argument size
576+ if (argc != 0 )
577+ {
578+ // TODO: This must be: return metacall::value<error>
579+ throw std::invalid_argument (
580+ " Incorrect number of arguments. Expected no arguments, received " +
581+ std::to_string (argc) +
582+ " arguments." );
583+ }
584+
585+ // Get target function from closure
586+ auto func = (Ret (*)(void ))(data);
587+
588+ // Execute the call
589+ auto result = func ();
590+
591+ // Generate return value
592+ return value<Ret>::create (result);
593+ };
594+
595+ enum metacall_value_id types[] = { METACALL_INVALID };
596+
597+ return metacall::metacall_registerv_closure (
598+ name,
599+ invoke,
600+ func_ptr,
601+ value<Ret>::id (),
602+ 0 ,
603+ types,
604+ (void *)(func));
605+ }
606+
607+ template <typename Ret, typename ... Args>
608+ int register_function (const char *name, Ret (*func)(Args...), void **func_ptr)
609+ {
610+ auto invoke = [](size_t argc, void *args[], void *data) -> void * {
611+ // Check for correct argument size
612+ if (argc != sizeof ...(Args))
613+ {
614+ // TODO: This must be: return metacall::value<error>
615+ throw std::invalid_argument (
616+ " Incorrect number of arguments. Expected " +
617+ std::to_string (sizeof ...(Args)) +
618+ " arguments, received " +
619+ std::to_string (argc) +
620+ " arguments." );
621+ }
622+
623+ // Convert arguments from the void* array to a typed tuple of metacall values
624+ auto tuple_args = register_function_args<Args...>(args);
625+
626+ // Get target function from closure
627+ auto func = (Ret (*)(Args...))(data);
628+
629+ // Apply the function to the unpacked arguments
630+ auto result = std::apply (func, tuple_args);
631+
632+ // Generate return value
633+ return value<Ret>::create (result);
634+ };
635+
636+ enum metacall_value_id types[] = { value<Args>::id ()... };
637+
638+ return metacall::metacall_registerv_closure (
639+ name,
640+ invoke,
641+ func_ptr,
642+ value<Ret>::id (),
643+ sizeof ...(Args),
644+ types,
645+ (void *)(func));
646+ }
647+
559648} /* namespace detail */
560649
650+ template <typename Ret, typename ... Args>
651+ class function
652+ {
653+ public:
654+ explicit function (void *func) :
655+ func(func) {}
656+
657+ ~function () {}
658+
659+ Ret operator ()(Args &&...args) const
660+ {
661+ constexpr std::size_t size = sizeof ...(Args);
662+ std::array<value_base, size> value_args = { { detail::to_value_base (std::forward<Args>(args))... } };
663+ void *raw_args[size];
664+
665+ for (std::size_t i = 0 ; i < size; ++i)
666+ {
667+ raw_args[i] = value_args[i].to_raw ();
668+ }
669+
670+ void *ret = metacallfv_s (func, raw_args, size);
671+
672+ if (ret == NULL )
673+ {
674+ throw std::runtime_error (" MetaCall invokation has failed by returning NULL" );
675+ }
676+
677+ value<Ret> result (ret, &metacall_value_destroy);
678+
679+ return result.to_value ();
680+ }
681+
682+ private:
683+ void *func;
684+ };
685+
686+ template <typename Ret, typename ... Args>
687+ void register_function (const char *name, Ret (*func)(Args...), void **func_ptr = nullptr)
688+ {
689+ if (detail::register_function (name, func, func_ptr) != 0 )
690+ {
691+ throw std::runtime_error (" Function '" + std::string (name) + " ' failed to be registered." );
692+ }
693+ }
694+
695+ template <typename Ret, typename ... Args>
696+ function<Ret, Args...> register_function (Ret (*func)(Args...))
697+ {
698+ void *func_ptr = nullptr ;
699+
700+ if (detail::register_function (NULL , func, &func_ptr) != 0 )
701+ {
702+ throw std::runtime_error (" Function failed to be registered." );
703+ }
704+
705+ return function<Ret, Args...>(func_ptr);
706+ }
707+
561708template <typename Ret, typename ... Args>
562709Ret metacall (std::string name, Args &&...args)
563710{
0 commit comments