Skip to content

Commit 77e9ddb

Browse files
committed
Improve cxx port.
1 parent 282887d commit 77e9ddb

File tree

4 files changed

+211
-70
lines changed

4 files changed

+211
-70
lines changed

source/ports/cxx_port/CMakeLists.txt

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,9 @@ include(SecurityFlags)
3434
# Sources
3535
#
3636

37-
set(inline_path "${CMAKE_CURRENT_SOURCE_DIR}/inline/metacall")
3837
set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/metacall")
3938
set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source")
4039

41-
set(inlines
42-
${inline_path}/metacall.inl
43-
)
44-
4540
set(headers
4641
${include_path}/metacall.hpp
4742
)
@@ -51,11 +46,8 @@ set(sources
5146
)
5247

5348
# Group source files
54-
set(inline_group "Inline Files")
5549
set(header_group "Header Files (API)")
5650
set(source_group "Source Files")
57-
source_group_by_path(${inline_path} "\\\\.inl$"
58-
${inline_group} ${inlines})
5951
source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$"
6052
${header_group} ${headers})
6153
source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$"
@@ -67,7 +59,6 @@ source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$"
6759

6860
# Build library
6961
add_library(${target}
70-
${inlines}
7162
${sources}
7263
${headers}
7364
)
@@ -104,22 +95,13 @@ target_include_directories(${target}
10495
${CMAKE_CURRENT_SOURCE_DIR}/include
10596
${CMAKE_CURRENT_BINARY_DIR}/include
10697

107-
${PROJECT_BINARY_DIR}/source/inline
108-
${CMAKE_CURRENT_SOURCE_DIR}/inline
109-
${CMAKE_CURRENT_BINARY_DIR}/inline
110-
11198
PUBLIC
11299
${DEFAULT_INCLUDE_DIRECTORIES}
113100

114101
INTERFACE
115102
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
116103
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
117104
$<INSTALL_INTERFACE:include>
118-
119-
120-
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inline>
121-
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/inline>
122-
$<INSTALL_INTERFACE:inline>
123105
)
124106

125107
#
@@ -165,6 +147,15 @@ target_compile_options(${target}
165147
INTERFACE
166148
)
167149

150+
#
151+
# Compile features
152+
#
153+
154+
target_compile_features(${target}
155+
PRIVATE
156+
cxx_std_17
157+
)
158+
168159
#
169160
# Linker options
170161
#
@@ -187,9 +178,3 @@ install(DIRECTORY
187178
${CMAKE_CURRENT_SOURCE_DIR}/include/metacall DESTINATION ${INSTALL_INCLUDE}
188179
COMPONENT dev
189180
)
190-
191-
# Inline files
192-
install(DIRECTORY
193-
${CMAKE_CURRENT_SOURCE_DIR}/inline/metacall DESTINATION ${INSTALL_INCLUDE}
194-
COMPONENT dev
195-
)

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

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ class METACALL_API value : public value_base
8686
throw std::runtime_error("Unsupported MetaCall value");
8787
}
8888

89-
private:
9089
// Type-specific creation (calls specialized version below)
9190
static void *create(const T &v);
9291

@@ -338,6 +337,123 @@ inline std::nullptr_t value<std::nullptr_t>::to_value() const
338337

339338
// TODO: Future, Function, Class, Object, Exception, Throwable...
340339

340+
class METACALL_API value_ref
341+
{
342+
public:
343+
explicit value_ref(void *ptr) :
344+
ptr(ptr) {}
345+
346+
template <typename T>
347+
T as() const
348+
{
349+
return value<T>(ptr).to_value();
350+
}
351+
352+
private:
353+
void *ptr;
354+
};
355+
356+
class METACALL_API array : public value_base
357+
{
358+
public:
359+
template <typename... Args>
360+
explicit array(Args &&...args) :
361+
value_base(create(std::forward<Args>(args)...), &metacall_value_destroy)
362+
{
363+
if (value_ptr == nullptr)
364+
{
365+
throw std::runtime_error("Failed to create MetaCall array");
366+
}
367+
}
368+
369+
explicit array(void *array_value) :
370+
value_base(array_value, &value_base::noop_destructor) {}
371+
372+
void **to_value() const
373+
{
374+
void **array_ptr = metacall_value_to_array(value_ptr.get());
375+
376+
if (array_ptr == NULL)
377+
{
378+
throw std::runtime_error("Invalid MetaCall array");
379+
}
380+
381+
return array_ptr;
382+
}
383+
384+
template <typename T>
385+
T get(std::size_t index) const
386+
{
387+
void **array_ptr = to_value();
388+
389+
return value<T>(array_ptr[index]).to_value();
390+
}
391+
392+
value_ref operator[](std::size_t index) const
393+
{
394+
void **array_ptr = to_value();
395+
396+
return value_ref(array_ptr[index]);
397+
}
398+
399+
static enum metacall_value_id id()
400+
{
401+
return METACALL_ARRAY;
402+
}
403+
404+
private:
405+
// Recursive function to create and fill the MetaCall array
406+
template <typename... Args>
407+
static void *create(Args &&...args)
408+
{
409+
constexpr std::size_t size = sizeof...(Args);
410+
411+
// Create the array with null data initially
412+
void *array_value = metacall_value_create_array(NULL, size);
413+
414+
if (array_value == NULL)
415+
{
416+
throw std::runtime_error("Failed to create MetaCall value array");
417+
}
418+
419+
// Get the internal C array
420+
void **array_ptr = metacall_value_to_array(array_value);
421+
422+
// Helper to unpack the args into array
423+
create_array(array_ptr, 0, std::forward<Args>(args)...);
424+
425+
return array_value;
426+
}
427+
428+
// Recursive unpacking using fold expression (C++17+)
429+
template <typename... Args>
430+
static void create_array(void **array_ptr, std::size_t index, Args &&...args)
431+
{
432+
// Use initializer list trick to expand the pack
433+
((
434+
array_ptr[index++] = value<std::decay_t<Args>>::create(std::forward<Args>(args))),
435+
...);
436+
}
437+
};
438+
439+
template <>
440+
inline void *value<array>::create(const array &v)
441+
{
442+
return metacall_value_copy(v.to_raw());
443+
}
444+
445+
template <>
446+
inline enum metacall_value_id value<array>::id()
447+
{
448+
return METACALL_ARRAY;
449+
}
450+
451+
template <>
452+
inline array value<array>::to_value() const
453+
{
454+
return array(to_raw());
455+
}
456+
341457
template <typename K, typename V>
342458
class METACALL_API map : public value_base
343459
{
@@ -422,12 +538,11 @@ class METACALL_API map : public value_base
422538
};
423539

424540
template <typename... Ts>
425-
METACALL_API int metacall(std::string name, Ts... ts);
541+
METACALL_API int metacall(std::string name, Ts... ts)
542+
{
543+
return 0;
544+
}
426545

427546
} /* namespace metacall */
428547

429-
// TODO: Move everything to metacall.inl
430-
431-
#include <metacall/metacall.inl>
432-
433548
#endif /* METACALL_HPP */

source/ports/cxx_port/inline/metacall/metacall.inl

Lines changed: 0 additions & 40 deletions
This file was deleted.

source/tests/metacall_cxx_port_test/source/metacall_cxx_port_test.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,48 @@ void *cxx_map_test(size_t argc, void *args[], void *data)
4646
return metacall_value_create_null();
4747
}
4848

49+
void *cxx_array_test(size_t argc, void *args[], void *data)
50+
{
51+
array a(args[0]);
52+
53+
(void)argc;
54+
(void)data;
55+
56+
EXPECT_EQ((float)a[0].as<int>(), (int)3);
57+
EXPECT_EQ((float)a[1].as<float>(), (float)4.0f);
58+
59+
EXPECT_EQ((float)a.get<int>(0), (int)3);
60+
EXPECT_EQ((float)a.get<float>(1), (float)4.0f);
61+
62+
printf("a[0] => %d\n", a[0].as<int>());
63+
printf("a[1] => %f\n", a[1].as<float>());
64+
fflush(stdout);
65+
66+
return metacall_value_create_null();
67+
}
68+
69+
void *cxx_map_array_test(size_t argc, void *args[], void *data)
70+
{
71+
map<std::string, array> m(args[0]);
72+
73+
(void)argc;
74+
(void)data;
75+
76+
EXPECT_STREQ(m["includes"][0].as<std::string>().c_str(), "/a/path");
77+
EXPECT_STREQ(m["includes"][1].as<std::string>().c_str(), "/another/path");
78+
79+
EXPECT_STREQ(m["libraries"][0].as<std::string>().c_str(), "/a/path");
80+
EXPECT_STREQ(m["libraries"][1].as<std::string>().c_str(), "/another/path");
81+
82+
printf("m['includes'][0] => %s\n", m["includes"][0].as<std::string>().c_str());
83+
printf("m['includes'][1] => %s\n", m["includes"][1].as<std::string>().c_str());
84+
85+
printf("m['libraries'][0] => %s\n", m["libraries"][0].as<std::string>().c_str());
86+
printf("m['libraries'][1] => %s\n", m["libraries"][1].as<std::string>().c_str());
87+
88+
return metacall_value_create_null();
89+
}
90+
4991
// TODO:
5092
/*
5193
void *cxx_recursive_map_test(size_t argc, void *args[], void *data)
@@ -89,6 +131,45 @@ TEST_F(metacall_cxx_port_test, DefaultConstructor)
89131
metacall_value_destroy(ret);
90132
}
91133

134+
{
135+
array a(3, 4.0f);
136+
137+
void *args[] = {
138+
a.to_raw()
139+
};
140+
141+
metacall_register("cxx_array_test", cxx_array_test, NULL, METACALL_NULL, 1, METACALL_ARRAY);
142+
143+
void *ret = metacallv_s("cxx_array_test", args, 1);
144+
145+
EXPECT_NE((void *)NULL, (void *)ret);
146+
147+
EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_NULL);
148+
149+
metacall_value_destroy(ret);
150+
}
151+
152+
{
153+
map<std::string, array> m = {
154+
{ "includes", array("/a/path", "/another/path") },
155+
{ "libraries", array("/a/path", "/another/path") }
156+
};
157+
158+
void *args[] = {
159+
m.to_raw()
160+
};
161+
162+
metacall_register("cxx_map_array_test", cxx_map_array_test, NULL, METACALL_NULL, 1, METACALL_MAP);
163+
164+
void *ret = metacallv_s("cxx_map_array_test", args, 1);
165+
166+
EXPECT_NE((void *)NULL, (void *)ret);
167+
168+
EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_NULL);
169+
170+
metacall_value_destroy(ret);
171+
}
172+
92173
// TODO:
93174
/*
94175
{

0 commit comments

Comments
 (0)