Add make_foreign_object() overload

It's only available when users define WRENPP_WITH_NAME_GUESSING
and it automatically retrieves the class name of T using
new code in guess_class_name.hpp. Only tested on gcc so far.
Microsoft compiler doesn't seem to understand consteval keyword.
This commit is contained in:
King_DuckZ 2022-04-29 12:32:59 +02:00
parent 10e3c9adac
commit 5d6575f328
7 changed files with 106 additions and 5 deletions

1
include/meson.build Normal file
View file

@ -0,0 +1 @@
subdir('wrenpp')

View file

@ -0,0 +1,63 @@
#include "string_bt.hpp"
#include <cstddef>
#include <utility>
namespace wren {
namespace detail {
consteval std::size_t find_last (const char* str, std::size_t len, char c) {
for (std::size_t z = len; z > 0; --z) {
if (str[z - 1] == c)
return z - 1;
}
return len;
}
consteval std::size_t find_token_end (const char* str, std::size_t len) {
for (std::size_t z = 0; z < len; ++z) {
const bool is_lower = str[z] >= 'a' and str[z] <= 'z';
const bool is_upper = str[z] >= 'A' and str[z] <= 'Z';
const bool is_num = str[z] >= '0' and str[z] <= '9';
const bool is_special = str[z] == '_' or str[z] == ':';
if (not (is_lower or is_upper or is_num or is_special))
return z;
}
return len;
}
template <typename T>
consteval auto guess_class_name_impl() {
#if defined(__GNUC__)
constexpr auto fname = __PRETTY_FUNCTION__;
constexpr auto fname_len = sizeof(__PRETTY_FUNCTION__) / sizeof(__PRETTY_FUNCTION__[0]) - 1;
static_assert(fname_len > 0);
# if defined(__clang__)
//clang: void figure_out_name() [T = MyTest]
# else
//gcc: void figure_out_name() [with T = MyTest]
# endif
constexpr auto last_colon = detail::find_last(fname, fname_len, ':');
constexpr auto last_space = detail::find_last(fname, fname_len, ' ');
constexpr auto last_whatever = (last_colon == fname_len ? last_space : last_colon);
constexpr auto from = last_whatever + (last_whatever == fname_len ? 0 : 1);
constexpr auto len = detail::find_token_end(fname + from, fname_len - from);
constexpr dhandy::bt::string<len> retval{std::make_index_sequence<len>{}, fname + from};
return retval;
//#elif defined(_MSC_VER)
//void __cdecl guess_class_name<class MyTest>(void)
//__FUNCSIG__
#else
# error "Unsupported compiler"
#endif
}
template <typename T, std::size_t S=guess_class_name_impl<T>().size()>
static constinit dhandy::bt::string g_class_names = {guess_class_name_impl<T>()};
} //namespace detail
template <typename T>
const char* guess_class_name() {
return detail::g_class_names<T>.data;
}
} //namespace wren

View file

@ -0,0 +1,16 @@
include_files = [
'configuration.hpp',
'def_configuration.hpp',
'error_type.hpp',
'guess_class_name.hpp',
'handle.hpp',
'has_method.hpp',
'meson.build',
'string_bt.hpp',
'StringCRC32.hpp',
'vm_fun.hpp',
'vm.hpp',
'wren_types.hpp',
]
install_data(sources: include_files, install_dir: 'include/wrenpp')

View file

@ -19,6 +19,9 @@
#include "vm.hpp"
#include "string_bt.hpp"
#if defined(WRENPP_WITH_NAME_GUESSING)
# include "guess_class_name.hpp"
#endif
#include <string>
#include <string_view>
#include <vector>
@ -67,6 +70,11 @@ namespace wren {
template <typename T, typename... Args>
T* make_foreign_object(VM& vm, const ModuleAndName& mn, Args&&... args);
#if defined(WRENPP_WITH_NAME_GUESSING)
template <typename T, typename... Args>
T* make_foreign_object(VM& vm, const char* module, Args&&... args);
#endif
template <auto V>
foreign_method_t make_method_bindable();
@ -315,6 +323,17 @@ namespace wren {
return obj;
}
#if defined(WRENPP_WITH_NAME_GUESSING)
template <typename T, typename... Args>
inline T* make_foreign_object(VM& vm, const char* module, Args&&... args) {
return make_foreign_object<T>(
vm,
ModuleAndName{module, guess_class_name<T>()},
std::forward<Args>(args)...
);
}
#endif
template <auto V>
inline foreign_method_t make_method_bindable() {
return detail::MakeMethodBindable<V>::make();

View file

@ -1,7 +1,7 @@
project('wrenpp', 'cpp',
version: '0.1.2',
meson_version: '>=0.49.2',
default_options: ['buildtype=release', 'cpp_std=c++17', 'b_ndebug=if-release'],
default_options: ['buildtype=release', 'cpp_std=c++20', 'b_ndebug=if-release']
)
wren_dep = dependency('wren', version: '>=0.2.0',
@ -14,7 +14,7 @@ wren_dep = dependency('wren', version: '>=0.2.0',
],
static: true,
)
public_incl = include_directories('include')
public_incl = [include_directories('include')]
os = host_machine.system()
if os == 'gnu'
@ -45,11 +45,13 @@ conf.set('FUNC_POINTER_SIZE', func_ptr_size)
conf.set('WRENPP_NAME', meson.project_name())
project_config_file = configure_file(
input: 'src/config.h.in',
output: 'config.h',
input: 'src/pvt_config.h.in',
output: 'pvt_config.h',
configuration: conf
)
subdir('include')
wrenpp = library(meson.project_name(),
project_config_file,
'src/vm.cpp',

View file

@ -21,7 +21,7 @@
#endif
#include "dynafunc_maker.hpp"
#include "config.h"
#include "pvt_config.h"
#include <algorithm>
#include <cassert>
#include <unistd.h> //for sysconf()