Skip to content

Commit e552a07

Browse files
committed
Improve register in cxx port.
1 parent bb72c37 commit e552a07

File tree

11 files changed

+212
-29
lines changed

11 files changed

+212
-29
lines changed

source/cli/metacallcli/source/application.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void application::repl()
6767
return NULL;
6868
};
6969

70-
int result = metacall_register_loaderv(metacall_loader("ext"), plugin_repl_handle, "exit", exit_command, METACALL_INVALID, 0, NULL);
70+
int result = metacall_register_loaderv(metacall_loader("ext"), plugin_repl_handle, "exit", exit_command, METACALL_INVALID, 0, NULL, NULL);
7171

7272
if (result != 0)
7373
{

source/loader/include/loader/loader.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ LOADER_API int loader_initialize(void);
5151

5252
LOADER_API int loader_is_initialized(const loader_tag tag);
5353

54-
LOADER_API int loader_register(const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[]);
54+
LOADER_API int loader_register(const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[], void *data);
5555

56-
LOADER_API int loader_register_impl(void *impl, void *handle, const char *name, loader_register_invoke invoke, type_id return_type, size_t arg_size, type_id args_type_id[]);
56+
LOADER_API int loader_register_handle(void *impl, void *handle, const char *name, loader_register_invoke invoke, type_id return_type, size_t arg_size, type_id args_type_id[], void *data);
5757

5858
LOADER_API void loader_detour(detour d);
5959

source/loader/include/loader/loader_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ LOADER_API plugin loader_host_initialize(void);
4444

4545
LOADER_API plugin loader_host_get(void);
4646

47-
LOADER_API int loader_host_register(loader_impl host, context ctx, const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[]);
47+
LOADER_API int loader_host_register(loader_impl host, context ctx, const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[], void *data);
4848

4949
#ifdef __cplusplus
5050
}

source/loader/source/loader.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,16 @@ int loader_is_initialized(const loader_tag tag)
192192
return loader_impl_is_initialized(plugin_impl_type(p, loader_impl));
193193
}
194194

195-
int loader_register(const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[])
195+
int loader_register(const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[], void *data)
196196
{
197197
loader_manager_impl manager_impl = plugin_manager_impl_type(&loader_manager, loader_manager_impl);
198198

199-
return loader_host_register(plugin_impl_type(manager_impl->host, loader_impl), NULL, name, invoke, func, return_type, arg_size, args_type_id);
199+
return loader_host_register(plugin_impl_type(manager_impl->host, loader_impl), NULL, name, invoke, func, return_type, arg_size, args_type_id, data);
200200
}
201201

202-
int loader_register_impl(void *impl, void *handle, const char *name, loader_register_invoke invoke, type_id return_type, size_t arg_size, type_id args_type_id[])
202+
int loader_register_handle(void *impl, void *handle, const char *name, loader_register_invoke invoke, type_id return_type, size_t arg_size, type_id args_type_id[], void *data)
203203
{
204-
return loader_host_register((loader_impl)impl, loader_impl_handle_context(handle), name, invoke, NULL, return_type, arg_size, args_type_id);
204+
return loader_host_register((loader_impl)impl, loader_impl_handle_context(handle), name, invoke, NULL, return_type, arg_size, args_type_id, data);
205205
}
206206

207207
void loader_detour(detour d)

source/loader/source/loader_host.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ plugin loader_host_get(void)
156156
return loader_host_plugin;
157157
}
158158

159-
int loader_host_register(loader_impl host, context ctx, const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[])
159+
int loader_host_register(loader_impl host, context ctx, const char *name, loader_register_invoke invoke, function *func, type_id return_type, size_t arg_size, type_id args_type_id[], void *data)
160160
{
161161
void **invoke_ptr = (void *)&invoke;
162162

@@ -204,6 +204,8 @@ int loader_host_register(loader_impl host, context ctx, const char *name, loader
204204
}
205205
}
206206

207+
function_bind(f, data);
208+
207209
if (func != NULL)
208210
{
209211
*func = f;

source/metacall/include/metacall/metacall.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,36 @@ METACALL_API int metacall_register(const char *name, void *(*invoke)(size_t, voi
810810
*/
811811
METACALL_API int metacall_registerv(const char *name, void *(*invoke)(size_t, void *[], void *), void **func, enum metacall_value_id return_type, size_t size, enum metacall_value_id types[]);
812812

813+
/**
814+
* @brief
815+
* Register a function by name @name and arguments @types with closure @data
816+
*
817+
* @param[in] name
818+
* Name of the function (if it is NULL, function is not registered into host scope)
819+
*
820+
* @param[in] invoke
821+
* Pointer to function invoke interface (argc, argv, data)
822+
*
823+
* @param[out] func
824+
* Will set the pointer to the function if the parameter is not null
825+
*
826+
* @param[in] return_type
827+
* Type of return value
828+
*
829+
* @param[in] size
830+
* Number of function arguments
831+
*
832+
* @param[in] types
833+
* List of parameter types
834+
*
835+
* @param[in] data
836+
* Data to be bind to the function, it will be accessible latter on by third parameter of @invoke
837+
*
838+
* @return
839+
* Pointer to value containing the result of the call
840+
*/
841+
METACALL_API int metacall_registerv_closure(const char *name, void *(*invoke)(size_t, void *[], void *), void **func, enum metacall_value_id return_type, size_t size, enum metacall_value_id types[], void *data);
842+
813843
/**
814844
* @brief
815845
* Obtain the loader instance by @tag
@@ -847,10 +877,13 @@ METACALL_API void *metacall_loader(const char *tag);
847877
* @param[in] types
848878
* List of parameter types
849879
*
880+
* @param[in] data
881+
* Data to be bind to the function, it will be accessible latter on by third parameter of @invoke
882+
*
850883
* @return
851884
* Zero if the function was registered properly, distinct from zero otherwise
852885
*/
853-
METACALL_API int metacall_register_loaderv(void *loader, void *handle, const char *name, void *(*invoke)(size_t, void *[], void *), enum metacall_value_id return_type, size_t size, enum metacall_value_id types[]);
886+
METACALL_API int metacall_register_loaderv(void *loader, void *handle, const char *name, void *(*invoke)(size_t, void *[], void *), enum metacall_value_id return_type, size_t size, enum metacall_value_id types[], void *data);
854887

855888
/**
856889
* @brief

source/metacall/source/metacall.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,22 +1600,27 @@ int metacall_register(const char *name, void *(*invoke)(size_t, void *[], void *
16001600

16011601
va_end(va);
16021602

1603-
return loader_register(name, (loader_register_invoke)invoke, (function *)func, (type_id)return_type, size, (type_id *)types);
1603+
return loader_register(name, (loader_register_invoke)invoke, (function *)func, (type_id)return_type, size, (type_id *)types, NULL);
16041604
}
16051605

16061606
int metacall_registerv(const char *name, void *(*invoke)(size_t, void *[], void *), void **func, enum metacall_value_id return_type, size_t size, enum metacall_value_id types[])
16071607
{
1608-
return loader_register(name, (loader_register_invoke)invoke, (function *)func, (type_id)return_type, size, (type_id *)types);
1608+
return loader_register(name, (loader_register_invoke)invoke, (function *)func, (type_id)return_type, size, (type_id *)types, NULL);
1609+
}
1610+
1611+
int metacall_registerv_closure(const char *name, void *(*invoke)(size_t, void *[], void *), void **func, enum metacall_value_id return_type, size_t size, enum metacall_value_id types[], void *data)
1612+
{
1613+
return loader_register(name, (loader_register_invoke)invoke, (function *)func, (type_id)return_type, size, (type_id *)types, data);
16091614
}
16101615

16111616
void *metacall_loader(const char *tag)
16121617
{
16131618
return loader_get_impl(tag);
16141619
}
16151620

1616-
int metacall_register_loaderv(void *loader, void *handle, const char *name, void *(*invoke)(size_t, void *[], void *), enum metacall_value_id return_type, size_t size, enum metacall_value_id types[])
1621+
int metacall_register_loaderv(void *loader, void *handle, const char *name, void *(*invoke)(size_t, void *[], void *), enum metacall_value_id return_type, size_t size, enum metacall_value_id types[], void *data)
16171622
{
1618-
return loader_register_impl(loader, handle, name, (loader_register_invoke)invoke, (type_id)return_type, size, (type_id *)types);
1623+
return loader_register_handle(loader, handle, name, (loader_register_invoke)invoke, (type_id)return_type, size, (type_id *)types, data);
16191624
}
16201625

16211626
void *metacall_await(const char *name, void *args[], void *(*resolve_callback)(void *, void *), void *(*reject_callback)(void *, void *), void *data)

source/plugin/include/plugin/plugin_interface.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
#define EXTENSION_FUNCTION_IMPL_VOID(ret, name) \
3939
do \
4040
{ \
41-
if (metacall_register_loaderv(loader, handle, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \
41+
if (metacall_register_loaderv(loader, handle, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL, NULL) != 0) \
4242
{ \
4343
log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \
4444
return 1; \
@@ -49,7 +49,7 @@
4949
do \
5050
{ \
5151
enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \
52-
if (metacall_register_loaderv(loader, handle, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \
52+
if (metacall_register_loaderv(loader, handle, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types, NULL) != 0) \
5353
{ \
5454
log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \
5555
return 1; \

source/ports/cxx_port/include/metacall/metacall.hpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
561708
template <typename Ret, typename... Args>
562709
Ret metacall(std::string name, Args &&...args)
563710
{

source/ports/rs_port/src/bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,7 @@ unsafe extern "C" {
10711071
return_type: metacall_value_id,
10721072
size: usize,
10731073
types: *mut metacall_value_id,
1074+
data: *mut ::std::os::raw::c_void,
10741075
) -> ::std::os::raw::c_int;
10751076
}
10761077
unsafe extern "C" {

0 commit comments

Comments
 (0)