├── README.md ├── .gitignore ├── example ├── hello.cpp └── main.cpp ├── LICENSE ├── include └── reflect │ ├── reflect │ ├── macros │ ├── object.h │ ├── field.h │ ├── private │ ├── dl.h │ └── macros.h │ ├── class.h │ └── method.h └── makefile /README.md: -------------------------------------------------------------------------------- 1 | reflect 2 | ======= 3 | 4 | C++ reflection framework (for fun) 5 | 6 | simple example: 7 | 8 | ```cpp 9 | #include 10 | 11 | int 12 | main() { 13 | rf::class_t clss = rf::class_t::for_name("hello_t"); 14 | rf::object_t object = clss.new_instance(); 15 | rf::method_t method = clss.get_method("say_hello"); 16 | method.invoke(object); 17 | } 18 | 19 | ``` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # target folder 31 | target -------------------------------------------------------------------------------- /example/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct hello_t { 4 | int i_var = 256; 5 | void say_hello() { 6 | std::cout << "hello world from reflected function" << std::endl; 7 | } 8 | 9 | int multiply_by_two(int x) { 10 | return x * 2; 11 | } 12 | }; 13 | 14 | rtti_type(hello_t); 15 | rtti_type(std, string); 16 | rtti_method(hello_t, say_hello, void); 17 | rtti_method(hello_t, multiply_by_two, int, int); 18 | rtti_field(hello_t, int, i_var); 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jeremy Letang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int 6 | main() { 7 | rf::class_t klass = rf::class_t::for_name("hello_t"); 8 | rf::object_t object = klass.new_instance(); 9 | if (klass == nullptr) { std::cout << "klass null" << std::endl; } 10 | if (object == nullptr) { std::cout << "object null" << std::endl; } 11 | rf::method_t method1 = klass.get_method("say_hello"); 12 | if (method1 == nullptr) { std::cout << "say_hello don't exist" << std::endl; } 13 | else { method1.invoke(object); } 14 | std::cout << method1.to_string() << std::endl; 15 | rf::method_t method2 = klass.get_method("multiply_by_two"); 16 | if (method2 == nullptr) { std::cout << "multiply_by_two don't exist" << std::endl; } 17 | else { std::cout << method2.invoke(object, 42) << std::endl; } 18 | std::cout << method2.to_string() << std::endl; 19 | rf::field_t field = klass.get_field("i_var"); 20 | std::cout << field.get(object) << std::endl; 21 | 22 | if (method2 != method1) { 23 | std::cout << "methods are different" << std::endl; 24 | } 25 | if (object != object) { 26 | std::cout << "objects are different" << std::endl; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /include/reflect/reflect: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2014 Jeremy Letang 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | #ifndef REFLECT_CXX 26 | #define REFLECT_CXX 27 | 28 | #include "class.h" 29 | #include "object.h" 30 | #include "method.h" 31 | #include "field.h" 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/reflect/macros: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2014 Jeremy Letang 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | #ifndef REFLECT_MACROS 26 | #define REFLECT_MACROS 27 | 28 | #include 29 | #include 30 | #include "private/macros.h" 31 | 32 | #define rtti_type(...) _rtti_type(narg(__VA_ARGS__), __VA_ARGS__) 33 | 34 | #define rtti_method(type, method, ...) _rtti_method(narg(__VA_ARGS__), type, method, __VA_ARGS__) 35 | 36 | #define rtti_field(type, field_type, field_name) \ 37 | extern "C" { \ 38 | field_type &_field_reflectable_##field_name##_##type(void *instance) { \ 39 | type *real_instance = static_cast(instance); \ 40 | return real_instance->field_name; \ 41 | } \ 42 | } \ 43 | 44 | #endif -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) 2014 Jeremy Letang 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | CC = g++ 24 | RM = rm -rf 25 | 26 | HOST = $(shell uname) 27 | 28 | INCLUDE_DIR = -Iinclude 29 | BUILD_DIR = target 30 | 31 | TEST_BIN = reflect_test 32 | TEST_SRC_DIR = example 33 | TEST_SRCS = $(wildcard $(TEST_SRC_DIR)/*.cpp) 34 | TEST_OBJS = $(subst .cpp,.o,$(TEST_SRCS)) 35 | 36 | CXXFLAGS = -Wall --std=c++11 $(INCLUDE_DIR) 37 | 38 | ifeq ($(HOST), Darwin) 39 | CXXFLAGS += -Wno-return-type-c-linkage 40 | endif 41 | 42 | all: $(TEST_BIN) 43 | 44 | $(TEST_BIN): $(TEST_OBJS) 45 | mkdir -p $(BUILD_DIR) 46 | ifeq ($(HOST), Linux) 47 | $(CC) -rdynamic -ldl -o $(BUILD_DIR)/$(TEST_BIN) $(TEST_OBJS) 48 | endif 49 | ifeq ($(HOST), Darwin) 50 | $(CC) -o $(BUILD_DIR)/$(TEST_BIN) $(TEST_OBJS) 51 | endif 52 | 53 | pre: 54 | ifeq ($(HOST), Linux) 55 | $(CC) -rdynamic -ldl -o $(BUILD_DIR)/$(TEST_BIN) $(TEST_OBJS) 56 | endif 57 | ifeq ($(HOST), Darwin) 58 | $(CC) -E $(INCLUDE_DIR) $(TEST_SRCS) 59 | endif 60 | 61 | clean: 62 | $(RM) $(TEST_OBJS) 63 | 64 | fclean: clean 65 | $(RM) $(BUILD_DIR) 66 | 67 | re: fclean all 68 | -------------------------------------------------------------------------------- /include/reflect/object.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef REFLECT_OBJECT 24 | #define REFLECT_OBJECT 25 | 26 | #include "class.h" 27 | 28 | namespace rf { 29 | 30 | class object_t { 31 | 32 | friend class class_t; 33 | 34 | private: 35 | 36 | std::string type_name_; 37 | void *ptr; 38 | 39 | object_t() = delete; 40 | object_t(std::string type_name, void *ptr) 41 | : type_name_(type_name), ptr(ptr) {} 42 | 43 | public: 44 | 45 | template T &get() { 46 | return *static_cast(this->ptr); 47 | } 48 | 49 | void *get_ptr() { 50 | return this->ptr; 51 | } 52 | 53 | std::string &type_name() { 54 | return this->type_name_; 55 | } 56 | 57 | bool operator==(object_t &oth) { 58 | return this->ptr == oth.ptr; 59 | } 60 | 61 | bool operator!=(object_t &oth) { 62 | return this->ptr != oth.ptr; 63 | } 64 | 65 | friend bool operator==(std::nullptr_t nullp, object_t &o); 66 | friend bool operator==(object_t &o, std::nullptr_t nullp); 67 | friend bool operator!=(std::nullptr_t nullp, object_t &o); 68 | friend bool operator!=(object_t &o, std::nullptr_t nullp); 69 | 70 | }; 71 | 72 | bool 73 | operator==(std::nullptr_t nullp, object_t &o) { 74 | return o.ptr == nullptr; 75 | } 76 | 77 | bool 78 | operator==(object_t &o, std::nullptr_t nullp) { 79 | return o.ptr == nullptr; 80 | } 81 | 82 | bool 83 | operator!=(std::nullptr_t nullp, object_t &o) { 84 | return o.ptr != nullptr; 85 | } 86 | 87 | bool 88 | operator!=(object_t &o, std::nullptr_t nullp) { 89 | return o.ptr != nullptr; 90 | } 91 | 92 | // FIXEM: get_class() -> class_t, 93 | 94 | } 95 | 96 | #endif -------------------------------------------------------------------------------- /include/reflect/field.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef REFLECT_FIELD 24 | #define REFLECT_FIELD 25 | 26 | #include 27 | #include "class.h" 28 | #include "object.h" 29 | 30 | namespace rf { 31 | 32 | class field_t { 33 | 34 | friend class class_t; 35 | 36 | private: 37 | 38 | std::string name_; 39 | std::string type_name_; 40 | void *(*ptr)(void*) = nullptr; 41 | 42 | field_t() = delete; 43 | field_t(std::string name, std::string type_name, void *(*ptr)(void*)) 44 | : name_(name), type_name_(type_name), ptr(ptr) {} 45 | 46 | public: 47 | 48 | template 49 | T &get(object_t &o) { 50 | T &(*func)(void*) = (T &(*)(void*))this->ptr; 51 | T &field = func(o.get_ptr()); 52 | return field; 53 | } 54 | 55 | std::string &get_name() { 56 | return this->name_; 57 | } 58 | 59 | std::string &type_name() { 60 | return this->type_name_; 61 | } 62 | 63 | bool operator==(field_t &oth) { 64 | return this->ptr == oth.ptr; 65 | } 66 | 67 | bool operator!=(field_t &oth) { 68 | return this->ptr == oth.ptr; 69 | } 70 | 71 | friend bool operator==(std::nullptr_t nullp, field_t &f); 72 | friend bool operator==(field_t &f, std::nullptr_t nullp); 73 | friend bool operator!=(std::nullptr_t nullp, field_t &f); 74 | friend bool operator!=(field_t &f, std::nullptr_t nullp); 75 | 76 | }; 77 | 78 | 79 | bool 80 | operator==(std::nullptr_t nullp, field_t &f) { 81 | return f.ptr == nullptr; 82 | } 83 | 84 | bool 85 | operator==(field_t &f, std::nullptr_t nullp) { 86 | return f.ptr == nullptr; 87 | } 88 | 89 | bool 90 | operator!=(std::nullptr_t nullp, field_t &f) { 91 | return f.ptr != nullptr; 92 | } 93 | 94 | bool 95 | operator!=(field_t &f, std::nullptr_t nullp) { 96 | return f.ptr != nullptr; 97 | } 98 | 99 | } 100 | 101 | #endif -------------------------------------------------------------------------------- /include/reflect/private/dl.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef REFLECT_DL 24 | #define REFLECT_DL 25 | 26 | #include 27 | 28 | namespace rf { 29 | 30 | namespace priv { 31 | 32 | typedef void *(*func_t)(); 33 | typedef void *(*meth_t)(void*); 34 | typedef const char *(*meth_to_string_t)(); 35 | 36 | class dl { 37 | 38 | private: 39 | 40 | void *handle = nullptr; 41 | 42 | dl() 43 | : handle(nullptr) {} 44 | 45 | void* make_handle() { 46 | // get handle 47 | void *handle_tmp = dlopen(NULL, RTLD_LAZY); 48 | 49 | // clear error 50 | dlerror(); 51 | 52 | return handle_tmp; 53 | } 54 | 55 | public: 56 | 57 | ~dl() { 58 | dlclose(this->handle); 59 | } 60 | 61 | static dl &get_instance() { 62 | static dl self; 63 | return self; 64 | } 65 | 66 | func_t get_constructor(std::string symbol) { 67 | if (this->handle == nullptr && (this->handle = this->make_handle()) == nullptr) { 68 | return nullptr; 69 | } 70 | void *(*constructor)() = nullptr; 71 | *(void **) (&constructor) = dlsym(this->handle, symbol.c_str()); 72 | return constructor; 73 | } 74 | 75 | meth_t get_method(std::string symbol) { 76 | if (this->handle == nullptr && (this->handle = this->make_handle()) == nullptr) { 77 | return nullptr; 78 | } 79 | void *(*method)(void*) = nullptr; 80 | *(void **) (&method) = dlsym(this->handle, symbol.c_str()); 81 | return method; 82 | } 83 | 84 | meth_to_string_t get_method_to_string(std::string symbol) { 85 | if (this->handle == nullptr && (this->handle = this->make_handle()) == nullptr) { 86 | return nullptr; 87 | } 88 | const char *(*method)() = nullptr; 89 | *(void **) (&method) = dlsym(this->handle, symbol.c_str()); 90 | return method; 91 | } 92 | 93 | }; 94 | 95 | } 96 | 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /include/reflect/class.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef REFLECT_CLASS 24 | #define REFLECT_CLASS 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "object.h" 31 | #include "method.h" 32 | #include "field.h" 33 | #include "private/dl.h" 34 | 35 | namespace rf { 36 | 37 | #define name_prefix "_instanciate_reflectable_type_"; 38 | #define method_prefix "_method_reflectable_" 39 | #define field_prefix "_field_reflectable_" 40 | 41 | class class_t { 42 | 43 | private: 44 | 45 | std::string name; 46 | void *(*constructor)() = nullptr; 47 | char *error = nullptr; 48 | 49 | class_t() 50 | : name(""), constructor(nullptr), error(nullptr) {} 51 | 52 | public: 53 | 54 | ~class_t() {} 55 | 56 | static class_t for_name(std::string class_name) { 57 | class_t class_tmp; 58 | 59 | class_tmp.name = class_name; 60 | 61 | // load function constructor 62 | std::string fn_name = name_prefix; 63 | fn_name += class_tmp.name; 64 | 65 | class_tmp.constructor = priv::dl::get_instance().get_constructor(fn_name); 66 | 67 | return class_tmp; 68 | } 69 | 70 | object_t new_instance() { 71 | void *ptr_instance = nullptr; 72 | 73 | if (this->constructor != nullptr) { 74 | ptr_instance = (*this->constructor)(); 75 | } 76 | 77 | return object_t(this->name, ptr_instance); 78 | } 79 | 80 | method_t get_method(std::string method_name) { 81 | void *(*ptr_method)(void*) = nullptr; 82 | 83 | // load function method 84 | std::string fn_name = method_prefix; 85 | fn_name += method_name; 86 | fn_name += "_"; 87 | fn_name += this->name; 88 | ptr_method = priv::dl::get_instance().get_method(fn_name); 89 | 90 | return method_t(method_name, this->name, ptr_method); 91 | } 92 | 93 | field_t get_field(std::string field_name) { 94 | void *(*ptr_method)(void*) = nullptr; 95 | 96 | // load function method 97 | std::string fn_name = field_prefix; 98 | fn_name += field_name; 99 | fn_name += "_"; 100 | fn_name += this->name; 101 | ptr_method = priv::dl::get_instance().get_method(fn_name); 102 | 103 | return field_t(field_name, this->name, ptr_method); 104 | } 105 | 106 | friend bool operator==(std::nullptr_t nullp, class_t &c); 107 | friend bool operator==(class_t &c, std::nullptr_t nullp); 108 | friend bool operator!=(std::nullptr_t nullp, class_t &c); 109 | friend bool operator!=(class_t &c, std::nullptr_t nullp); 110 | 111 | }; 112 | 113 | bool 114 | operator==(std::nullptr_t nullp, class_t &c) { 115 | return c.constructor == nullptr; 116 | } 117 | 118 | bool 119 | operator==(class_t &c, std::nullptr_t nullp) { 120 | return c.constructor == nullptr; 121 | } 122 | 123 | bool 124 | operator!=(std::nullptr_t nullp, class_t &c) { 125 | return c.constructor != nullptr; 126 | } 127 | 128 | bool 129 | operator!=(class_t &c, std::nullptr_t nullp) { 130 | return c.constructor != nullptr; 131 | } 132 | 133 | // FIXME: is_instance(Object obj), get_name, to_string 134 | 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /include/reflect/method.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef REFLECT_METHOD 24 | #define REFLECT_METHOD 25 | 26 | #include 27 | #include "class.h" 28 | #include "object.h" 29 | #include "private/dl.h" 30 | 31 | namespace rf { 32 | 33 | #define method_parameters_type_prefix "_method_reflectable_parameters_type_" 34 | #define method_return_type_prefix "_method_reflectable_return_type_" 35 | 36 | class method_t { 37 | 38 | friend class class_t; 39 | 40 | private: 41 | 42 | std::string name_; 43 | std::string type_name_; 44 | void *(*ptr)(void*) = nullptr; 45 | 46 | std::string to_string_ = ""; 47 | std::string return_type_ = ""; 48 | std::string parameters_type_ = ""; 49 | 50 | method_t() = delete; 51 | method_t(std::string name, std::string type_name, void *(*ptr)(void*)) 52 | : name_(name), type_name_(type_name), ptr(ptr) {} 53 | 54 | public: 55 | 56 | template 57 | R invoke(object_t &o, P... params) { 58 | std::function (*func)(void*) = (std::function (*)(void*))this->ptr; 59 | auto fn = func(o.get_ptr()); 60 | return fn(params...); 61 | } 62 | 63 | std::string &name() { 64 | return this->name_; 65 | } 66 | 67 | std::string &type_name() { 68 | return this->type_name_; 69 | } 70 | 71 | std::string &to_string() { 72 | if (this->to_string_ == "") { 73 | this->to_string_ += this->return_type(); 74 | this->to_string_ += " "; 75 | this->to_string_ += this->name_; 76 | this->to_string_ += "("; 77 | this->to_string_ += this->parameters_type(); 78 | this->to_string_ += ")"; 79 | } 80 | 81 | return this->to_string_; 82 | } 83 | 84 | std::string &return_type() { 85 | if (this->return_type_ == "") { 86 | const char *(*ptr_method)(); 87 | std::string fn_name = method_return_type_prefix; 88 | fn_name += this->name_; 89 | fn_name += "_"; 90 | fn_name += this->type_name_; 91 | ptr_method = priv::dl::get_instance().get_method_to_string(fn_name); 92 | this->return_type_ = ptr_method(); 93 | } 94 | 95 | return this->return_type_; 96 | } 97 | 98 | std::string ¶meters_type() { 99 | if (this->parameters_type_ == "") { 100 | const char *(*ptr_method)(); 101 | std::string fn_name = method_parameters_type_prefix; 102 | fn_name += this->name_; 103 | fn_name += "_"; 104 | fn_name += this->type_name_; 105 | ptr_method = priv::dl::get_instance().get_method_to_string(fn_name); 106 | this->parameters_type_ = ptr_method(); 107 | } 108 | 109 | return this->parameters_type_; 110 | } 111 | 112 | bool operator==(method_t &oth) { 113 | return this->ptr == oth.ptr; 114 | } 115 | 116 | bool operator!=(method_t &oth) { 117 | return this->ptr != oth.ptr; 118 | } 119 | 120 | friend bool operator==(std::nullptr_t nullp, method_t &c); 121 | friend bool operator==(method_t &c, std::nullptr_t nullp); 122 | friend bool operator!=(std::nullptr_t nullp, method_t &c); 123 | friend bool operator!=(method_t &c, std::nullptr_t nullp); 124 | 125 | }; 126 | 127 | bool 128 | operator==(std::nullptr_t nullp, method_t &c) { 129 | return c.ptr == nullptr; 130 | } 131 | 132 | bool 133 | operator==(method_t &c, std::nullptr_t nullp) { 134 | return c.ptr == nullptr; 135 | } 136 | 137 | bool 138 | operator!=(std::nullptr_t nullp, method_t &c) { 139 | return c.ptr != nullptr; 140 | } 141 | 142 | bool 143 | operator!=(method_t &c, std::nullptr_t nullp) { 144 | return c.ptr != nullptr; 145 | } 146 | 147 | } 148 | 149 | #endif -------------------------------------------------------------------------------- /include/reflect/private/macros.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // type 24 | 25 | #define _rtti_type_1(arg1) \ 26 | extern "C" { \ 27 | void *_instanciate_reflectable_type_##arg1() { \ 28 | return new arg1(); \ 29 | } \ 30 | } 31 | 32 | #define _rtti_type_2(arg1, arg2) \ 33 | extern "C" { \ 34 | void *_instanciate_reflectable_type_##arg1##_##arg2() { \ 35 | return new arg1::arg2(); \ 36 | } \ 37 | } 38 | 39 | #define _rtti_type_3(arg1, arg2, arg3) \ 40 | extern "C" { \ 41 | void *_instanciate_reflectable_type_##arg1##_##arg2##_##arg3() { \ 42 | return new arg1::arg2::arg3(); \ 43 | } \ 44 | } 45 | 46 | #define _rtti_type_4(arg1, arg2, arg3, arg4) \ 47 | extern "C" { \ 48 | void *_instanciate_reflectable_type_##arg1##_##arg2##_##arg3##_##arg4() { \ 49 | return new arg1::arg2::arg3::arg4(); \ 50 | } \ 51 | } 52 | 53 | #define _rtti_type_5(arg1, arg2, arg3, arg4, arg5) \ 54 | extern "C" { \ 55 | void *_instanciate_reflectable_type_##arg1##_##arg2##_##arg3##_##arg4##_##arg5() { \ 56 | return new arg1::arg2::arg3::arg4::arg5(); \ 57 | } \ 58 | } 59 | 60 | #define narg(...) narg_(__VA_ARGS__, rseq_n()) 61 | #define narg_(...) arg_n(__VA_ARGS__) 62 | #define arg_n(_1, _2, _3, _4, _5, N, ...) N 63 | #define rseq_n() 5, 4, 3, 2, 1, 0 64 | 65 | #define concatenate(arg1, arg2) arg1##arg2 66 | 67 | #define _rtti_type(N, ...) concatenate(_rtti_type_, N)(__VA_ARGS__) 68 | 69 | // methods 70 | 71 | #define stringify_1(arg1) #arg1 72 | #define stringify_2(arg1, arg2) #arg2 73 | #define stringify_3(arg1, arg2, arg3) #arg3 74 | #define stringify_4(arg1, arg2, arg3, arg4) #arg4 75 | 76 | #define _decl_method_return_type(type, method, ret) \ 77 | const char *_method_reflectable_return_type_##method##_##type() { \ 78 | static std::string name(""); \ 79 | if (name == "") { \ 80 | name = stringify_1(ret); \ 81 | } \ 82 | return name.c_str(); \ 83 | } \ 84 | 85 | #define _rtti_method_1(type, method, ret) \ 86 | extern "C" { \ 87 | std::function _method_reflectable_##method##_##type(void *instance) { \ 88 | std::function func = std::bind(&type::method, static_cast(instance)); \ 89 | return func; \ 90 | } \ 91 | _decl_method_return_type(type, method, ret); \ 92 | const char *_method_reflectable_parameters_type_##method##_##type() { \ 93 | static std::string name(""); \ 94 | return name.c_str(); \ 95 | } \ 96 | } \ 97 | 98 | #define _rtti_method_2(type, method, ret, ...) \ 99 | extern "C" { \ 100 | std::function _method_reflectable_##method##_##type(void *instance) { \ 101 | std::function func = std::bind(&type::method, static_cast(instance), std::placeholders::_1); \ 102 | return func; \ 103 | } \ 104 | _decl_method_return_type(type, method, ret); \ 105 | const char *_method_reflectable_parameters_type_##method##_##type() { \ 106 | static std::string name(""); \ 107 | if (name == "") { \ 108 | name = stringify_1(__VA_ARGS__); \ 109 | } \ 110 | return name.c_str(); \ 111 | } \ 112 | } \ 113 | 114 | #define _rtti_method_3(type, method, ret, ...) \ 115 | extern "C" { \ 116 | std::function _method_reflectable_##method##_##type(void *instance) { \ 117 | std::function func = std::bind(&type::method, static_cast(instance), std::placeholders::_1, std::placeholders::_2); \ 118 | return func; \ 119 | } \ 120 | _decl_method_return_type(type, method, ret); \ 121 | const char *_method_reflectable_parameters_type_##method##_##type() { \ 122 | static std::string name(""); \ 123 | if (name == "") { \ 124 | name += stringify_1(__VA_ARGS__); \ 125 | name += ", "; \ 126 | name += stringify_2(__VA_ARGS__); \ 127 | } \ 128 | return name.c_str(); \ 129 | } \ 130 | } \ 131 | 132 | #define _rtti_method_4(type, method, ret, ...) \ 133 | extern "C" { \ 134 | std::function _method_reflectable_##method##_##type(void *instance) { \ 135 | std::function func = std::bind(&type::method, static_cast(instance), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); \ 136 | return func; \ 137 | } \ 138 | _decl_method_return_type(type, method, ret); \ 139 | const char *_method_reflectable_parameters_type_##method##_##type() { \ 140 | static std::string name(""); \ 141 | if (name == "") { \ 142 | name += stringify_1(__VA_ARGS__); \ 143 | name += ", "; \ 144 | name += stringify_2(__VA_ARGS__); \ 145 | name += ", "; \ 146 | name += stringify_3(__VA_ARGS__); \ 147 | } \ 148 | return name.c_str(); \ 149 | } \ 150 | } \ 151 | 152 | #define _rtti_method_5(type, method, ret, ...) \ 153 | extern "C" { \ 154 | std::function _method_reflectable_##method##_##type(void *instance) { \ 155 | std::function func = std::bind(&type::method, static_cast(instance), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); \ 156 | return func; \ 157 | } \ 158 | _decl_method_return_type(type, method, ret); \ 159 | const char *_method_reflectable_parameters_type_##method##_##type() { \ 160 | static std::string name(""); \ 161 | if (name == "") { \ 162 | name += stringify_1(__VA_ARGS__); \ 163 | name += ", "; \ 164 | name += stringify_2(__VA_ARGS__); \ 165 | name += ", "; \ 166 | name += stringify_3(__VA_ARGS__); \ 167 | name += ", "; \ 168 | name += stringify_4(__VA_ARGS__); \ 169 | } \ 170 | return name.c_str(); \ 171 | } \ 172 | } \ 173 | 174 | #define _rtti_method(N, type, method, ...) concatenate(_rtti_method_, N)(type, method, __VA_ARGS__) 175 | 176 | --------------------------------------------------------------------------------