├── .clang-format ├── .github └── workflows │ └── CI.yml ├── .gitignore ├── .releaserc ├── .vscode ├── c_cpp_properties.json ├── settings.json └── tasks.json ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── genepiConfig.cmake.in └── utils.cmake ├── examples ├── CMakeLists.txt ├── classes │ ├── classes.cpp │ └── classes.js ├── functions │ ├── functions.cpp │ └── functions.js ├── index.js ├── inherit │ ├── inherit.cpp │ └── inherit.js ├── methods │ ├── methods.cpp │ └── methods.js ├── objects │ ├── objects.cpp │ └── objects.js ├── overloaded-functions │ ├── overloaded-functions.cpp │ └── overloaded-functions.js └── overloaded-methods │ ├── overloaded-methods.cpp │ └── overloaded-methods.js ├── include └── genepi │ ├── arg_from_napi_value.h │ ├── bind_class.h │ ├── bind_class_base.h │ ├── binding_std.h │ ├── binding_type.h │ ├── callable.h │ ├── caller.h │ ├── checker.h │ ├── class_definer.h │ ├── class_wrapper.h │ ├── common.h │ ├── creator.h │ ├── function_definer.h │ ├── function_definition.h │ ├── genepi.h │ ├── genepi_registry.h │ ├── method_definition.h │ ├── signature │ ├── base_signature.h │ ├── constructor_signature.h │ ├── function_signature.h │ ├── method_signature.h │ ├── signature_param.h │ └── templated_base_signature.h │ ├── singleton.h │ ├── type_list.h │ ├── type_transformer.h │ └── types.h ├── package-lock.json ├── package.json └── src └── genepi ├── common.cpp ├── genepi_registry.cpp └── singleton.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | # clang-format configuration file based on the version 3.8 2 | # releases.llvm.org/3.8.0/tools/clang/docs/ClangFormatStyleOptions.html 3 | #BasedOnStyle (desactivated since we want to control everything [BC]) 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: DontAlign 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | # If AlignEscapedNewlinesLeft is false, that put as far right as possible, 9 | # else left. In newer clang-format version, 10 | #use AlignEscapedNewlines: Right instead. 11 | AlignEscapedNewlinesLeft: false 12 | AlignOperands: true 13 | AlignTrailingComments: false 14 | AllowAllParametersOfDeclarationOnNextLine: true 15 | AllowShortBlocksOnASingleLine: true 16 | AllowShortCaseLabelsOnASingleLine: false 17 | AllowShortFunctionsOnASingleLine: Empty # pb with 3.5 18 | AllowShortIfStatementsOnASingleLine: false 19 | AllowShortLoopsOnASingleLine: false 20 | #AlwaysBreakAfterDefinitionReturnType (not set because deprecated [BC]) 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: true 24 | BinPackArguments: true 25 | BinPackParameters: false 26 | BraceWrapping: 27 | AfterClass: true 28 | AfterControlStatement: true 29 | AfterEnum: true 30 | AfterFunction: true 31 | AfterNamespace: true 32 | AfterObjCDeclaration: true 33 | AfterStruct: true 34 | AfterUnion: true 35 | BeforeCatch: true 36 | BeforeElse: true 37 | IndentBraces: false 38 | #SplitEmptyFunctionBody: false (this option provokes a clang-format error [BC]) 39 | BreakBeforeBinaryOperators: NonAssignment # pb with 3.5 40 | BreakBeforeBraces: Custom # pb with 3.5 41 | #BreakBeforeInheritanceComma: false (this option needs a newer clang version) 42 | BreakBeforeTernaryOperators: true 43 | # For newer clang version, consider the new macro: 44 | # BreakConstructorInitializers 45 | BreakConstructorInitializersBeforeComma: false 46 | #BreakStringLiterals 47 | ColumnLimit: 80 48 | CommentPragmas: '' 49 | #CompactNamespaces: false (this option is in newer clang version) 50 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 51 | ConstructorInitializerIndentWidth: 4 52 | ContinuationIndentWidth: 4 53 | Cpp11BracedListStyle: false 54 | DerivePointerAlignment: true 55 | DisableFormat: false 56 | #ExperimentalAutoDetectBinPacking (Not defined since the documentation to not use it) 57 | #FixNamespaceComments: false (this option needs a newer clang version) 58 | #ForEachMacros: TODO 59 | #IncludeCategories: TODO 60 | #IncludeIsMainRegex (this option needs a newer clang version) 61 | IndentCaseLabels: false 62 | IndentWidth: 4 63 | IndentWrappedFunctionNames: true 64 | KeepEmptyLinesAtTheStartOfBlocks: false 65 | Language: Cpp 66 | #MacroBlockBegin TODO 67 | #MacroBlockEnd TODO 68 | MaxEmptyLinesToKeep: 1 69 | NamespaceIndentation: All 70 | #PenaltyBreakBeforeFirstCallParameter TODO 71 | #PenaltyBreakComment TODO 72 | #PenaltyBreakFirstLessLess TODO 73 | #PenaltyBreakString TODO 74 | #PenaltyExcessCharacter TODO 75 | #PenaltyReturnTypeOnItsOwnLine TODO 76 | PointerAlignment: Left 77 | ReflowComments: true # TODO check if 3.5 or 3.8 78 | #SortIncludes (this option needs a newer clang version) 79 | #SortUsingDeclarations (this option needs a newer clang version) 80 | SpaceAfterCStyleCast: true 81 | #SpaceAfterTemplateKeyword: false (this option needs a newer clang version) 82 | SpaceBeforeAssignmentOperators: true 83 | SpaceBeforeParens: Never 84 | SpaceInEmptyParentheses: false 85 | SpacesBeforeTrailingComments: 1 86 | SpacesInAngles: true 87 | SpacesInCStyleCastParentheses: false 88 | SpacesInContainerLiterals: false 89 | SpacesInParentheses: true 90 | SpacesInSquareBrackets: false 91 | Standard: Cpp11 92 | TabWidth: 4 93 | UseTab: Never 94 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }} 10 | 11 | strategy: 12 | matrix: 13 | node-version: [12.x, 14.x] 14 | os: [ubuntu-latest, windows-latest, macos-latest] 15 | 16 | steps: 17 | - uses: actions/checkout@v1 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - name: npm install and build 23 | run: | 24 | npm install 25 | npm run examples 26 | 27 | semantic-release: 28 | runs-on: ubuntu-latest 29 | needs: build 30 | steps: 31 | - uses: actions/checkout@v1 32 | - run: npx semantic-release 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.TOKEN }} 35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | - name: Notify slack 37 | if: failure() && github.ref == 'refs/heads/master' 38 | uses: 8398a7/action-slack@v2 39 | with: 40 | status: failure 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | node_modules 4 | .vscode/ipch -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | '@semantic-release/commit-analyzer', 4 | '@semantic-release/release-notes-generator', 5 | '@semantic-release/github', 6 | '@semantic-release/npm' 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "compilerPath": "/usr/bin/clang", 6 | "intelliSenseMode": "clang-x64" 7 | } 8 | ], 9 | "version": 4 10 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.default.cppStandard": "c++11", 3 | "C_Cpp.default.includePath": [ 4 | "${workspaceFolder}/include", 5 | "${workspaceFolder}/node_modules/node-addon-api", 6 | "${env:HOME}/.cmake-js/node-x64/v10.9.0/include/node" 7 | ], 8 | "C_Cpp.dimInactiveRegions": false, 9 | "files.associations": { 10 | "type_traits": "cpp", 11 | "array": "cpp", 12 | "functional": "cpp", 13 | "istream": "cpp", 14 | "ostream": "cpp", 15 | "tuple": "cpp", 16 | "utility": "cpp", 17 | "*.tcc": "cpp", 18 | "deque": "cpp", 19 | "vector": "cpp", 20 | "cctype": "cpp", 21 | "clocale": "cpp", 22 | "cmath": "cpp", 23 | "cstdarg": "cpp", 24 | "cstdint": "cpp", 25 | "cstdio": "cpp", 26 | "cstdlib": "cpp", 27 | "cstring": "cpp", 28 | "cwchar": "cpp", 29 | "cwctype": "cpp", 30 | "forward_list": "cpp", 31 | "unordered_map": "cpp", 32 | "unordered_set": "cpp", 33 | "exception": "cpp", 34 | "fstream": "cpp", 35 | "initializer_list": "cpp", 36 | "iosfwd": "cpp", 37 | "iostream": "cpp", 38 | "limits": "cpp", 39 | "memory": "cpp", 40 | "new": "cpp", 41 | "optional": "cpp", 42 | "sstream": "cpp", 43 | "stdexcept": "cpp", 44 | "streambuf": "cpp", 45 | "string_view": "cpp", 46 | "system_error": "cpp", 47 | "typeinfo": "cpp", 48 | "algorithm": "cpp", 49 | "cstddef": "cpp", 50 | "atomic": "cpp", 51 | "iterator": "cpp", 52 | "map": "cpp", 53 | "memory_resource": "cpp", 54 | "numeric": "cpp", 55 | "random": "cpp", 56 | "string": "cpp", 57 | "cinttypes": "cpp", 58 | "bit": "cpp" 59 | }, 60 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "build", 9 | "problemMatcher": [ 10 | "$gcc" 11 | ], 12 | "group": { 13 | "kind": "build", 14 | "isDefault": true 15 | } 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019 - 2021 Geode-solutions 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | cmake_minimum_required(VERSION 3.5) 22 | 23 | project(genepi) 24 | 25 | set(UTILS_FILE "${PROJECT_SOURCE_DIR}/cmake/utils.cmake") 26 | file(READ "${UTILS_FILE}" GENEPI_UTILS) 27 | include("${UTILS_FILE}") 28 | 29 | set(genepi_include_dir "${PROJECT_SOURCE_DIR}/include/genepi") 30 | set(genepi_source_dir "${PROJECT_SOURCE_DIR}/src/genepi") 31 | add_library(genepi "${genepi_source_dir}/genepi_registry.cpp") 32 | add_library(genepi::genepi ALIAS genepi) 33 | set_target_properties(genepi PROPERTIES POSITION_INDEPENDENT_CODE ON) 34 | target_sources(genepi 35 | PRIVATE 36 | "${genepi_include_dir}/arg_from_napi_value.h" 37 | "${genepi_include_dir}/bind_class.h" 38 | "${genepi_include_dir}/bind_class_base.h" 39 | "${genepi_include_dir}/binding_std.h" 40 | "${genepi_include_dir}/binding_type.h" 41 | "${genepi_include_dir}/caller.h" 42 | "${genepi_include_dir}/checker.h" 43 | "${genepi_include_dir}/class_definer.h" 44 | "${genepi_include_dir}/class_wrapper.h" 45 | "${genepi_include_dir}/common.h" 46 | "${genepi_include_dir}/creator.h" 47 | "${genepi_include_dir}/function_definer.h" 48 | "${genepi_include_dir}/function_definition.h" 49 | "${genepi_include_dir}/genepi.h" 50 | "${genepi_include_dir}/genepi_registry.h" 51 | "${genepi_include_dir}/method_definition.h" 52 | "${genepi_include_dir}/signature/base_signature.h" 53 | "${genepi_include_dir}/signature/constructor_signature.h" 54 | "${genepi_include_dir}/signature/function_signature.h" 55 | "${genepi_include_dir}/signature/method_signature.h" 56 | "${genepi_include_dir}/signature/signature_param.h" 57 | "${genepi_include_dir}/signature/templated_base_signature.h" 58 | "${genepi_include_dir}/singleton.h" 59 | "${genepi_include_dir}/types.h" 60 | "${genepi_include_dir}/type_list.h" 61 | "${genepi_include_dir}/type_transformer.h" 62 | "${genepi_source_dir}/singleton.cpp" 63 | ) 64 | target_include_directories(genepi 65 | PUBLIC 66 | ${PROJECT_SOURCE_DIR}/include 67 | ${PROJECT_BINARY_DIR} 68 | PRIVATE 69 | ${NODE_ADDON_API_DIR} 70 | ${CMAKE_JS_INC} 71 | ) 72 | 73 | target_link_libraries(genepi PUBLIC ${CMAKE_JS_LIB}) 74 | export(TARGETS genepi NAMESPACE genepi:: FILE genepi_target.cmake) 75 | include(GenerateExportHeader) 76 | generate_export_header(genepi 77 | EXPORT_MACRO_NAME genepi_api 78 | EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/genepi/genepi_export.h 79 | ) 80 | include(CMakePackageConfigHelpers) 81 | configure_package_config_file( 82 | cmake/genepiConfig.cmake.in 83 | genepiConfig.cmake 84 | INSTALL_DESTINATION . 85 | ) 86 | 87 | if(EXISTS ${PROJECT_SOURCE_DIR}/examples) 88 | add_subdirectory(examples) 89 | endif() 90 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - 2021 Geode-solutions 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Genepiby Geode-solutions

2 |

Automatic generation of N-API wrapper from a C++ library

3 | 4 |

5 | Build Status 6 | Version 7 |

8 | 9 |

10 | Windows support 11 | Linux support 12 | macOS support 13 |

14 | 15 |

16 | Language 17 | License 18 | Semantic-release 19 | Slack invite 20 |

21 | 22 | --- 23 | 24 | ## Introduction 25 | `genepi` is a C++11 library providing a complete set of macros to generate a Node.js addon from your C++ code using N-API. 26 | 27 | `genepi` works with [cmake-js](https://github.com/cmake-js/cmake-js) (a Node.js native addon of [CMake](https://cmake.org/)) as build system. CMake is largely used in the C++ community, here are some arguments to why CMake is a great build system for Node.js addons: [link](https://github.com/cmake-js/cmake-js#why-cmake). 28 | 29 | `genepi` is **MIT licensed** and based on templates and macros inspired by [nbind](https://github.com/charto/nbind) but using N-API. 30 | 31 | ## Features 32 | `genepi` allows you to: 33 | 34 | - Use your C++ API from JavaScript without any extra effort. 35 | - From **Node.js** and **Electron**, 36 | - On Linux, macOS and Windows, 37 | - Without changes to your C++ code. Simply add a separate short description at the end. 38 | - Distribute **native** code binary. 39 | 40 | In more detail: 41 | 42 | - Export C++ classes, even ones not visible from other files. 43 | - Export multiple C++ inheritances, even between several libraries. 44 | - Export C++ methods simply by mentioning their names. 45 | - Auto-detect argument and return types from C++ declarations. 46 | - [Automatically convert types](#type-conversion) and data structures between languages. 47 | - Call C++ methods from JavaScript with type checking. 48 | - Pass instances of compatible classes by value between languages (through the C++ stack). 49 | 50 | ## Requirements 51 | You need [Node.js](https://nodejs.org/) (at least v10.x) and one of the following C++ compilers: 52 | 53 | - GCC 4.8 or above, 54 | - Clang 3.6 or above, 55 | - Visual Studio 2015 ([the Community version](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) is fine). 56 | 57 | ## Quick start 58 | 1. Use your already existing C++ code in JavaScript 59 | 60 | ```C++ 61 | // My C++ code in hello.cpp 62 | #include 63 | #include 64 | 65 | struct Greeter { 66 | static void sayHello( const std::string& name ) 67 | { 68 | std::cout << "Hello, " << name << std::endl; 69 | } 70 | }; 71 | ``` 72 | 73 | 2. Install genepi and add some scripts to the `package.json` 74 | ```Shell 75 | npm install @geode/genepi 76 | ``` 77 | 78 | ```JSON 79 | { 80 | "scripts": { 81 | "build": "cmake-js compile", 82 | "build:debug": "cmake-js compile -D" 83 | } 84 | } 85 | ``` 86 | 87 | 3. Add JavaScript binding 88 | 89 | ```C++ 90 | // Add this to the file (or in another file) 91 | #include 92 | 93 | GENEPI_CLASS( Greeter ) 94 | { 95 | GENEPI_METHOD( sayHello ); 96 | } 97 | GENEPI_MODULE( hello ) 98 | ``` 99 | 100 | 4. Configure your project by creating a `CMakeLists.txt` 101 | ```CMake 102 | cmake_minimum_required(VERSION 3.5) 103 | 104 | project(my_project) 105 | 106 | find_package(genepi REQUIRED PATHS ${PROJECT_SOURCE_DIR}/node_modules/@geode/genepi/build) 107 | 108 | add_genepi_library(my_project "hello.cpp") 109 | ``` 110 | 111 | 5. Compile your addon 112 | ```Shell 113 | npm run build 114 | ``` 115 | 116 | 6. Use it! 117 | ```JavaScript 118 | var myProject = require('my_project.node'); 119 | myProject.Greeter.sayHello('you'); 120 | ``` 121 | 122 | ## User guide 123 | - [Creating your project](#creating-your-project) 124 | - [Calling from Node.js](#calling-from-nodejs) 125 | - [Functions](#functions) 126 | - [Overloaded functions](#overloaded-functions) 127 | - [Classes and constructors](#classes-and-constructors) 128 | - [Methods](#methods) 129 | - [Overloaded methods](#overloaded-methods) 130 | - [Inheritance](#inheritance) 131 | - [Passing data structures](#passing-data-structures) 132 | - [Using objects](#using-objects) 133 | - [Type conversion](#type-conversion) 134 | 135 | ### Creating your project 136 | Create your repository using the provided Github template: [genepi-template](https://github.com/Geode-solutions/genepi-template). 137 | Here is how to use a Github template: [link](https://help.github.com/en/articles/creating-a-repository-from-a-template). 138 | 139 | ### Calling from Node.js 140 | Each `genepi` module (i.e. each Node.js addon generated) needs to be registered using the `GENEPI_MODULE` macro: 141 | 142 | ```C++ 143 | // My C++ library 144 | 145 | GENEPI_MODULE( my_addon ); 146 | ``` 147 | 148 | This name `my_addon` is only used by [N-API](https://nodejs.org/api/n-api.html#n_api_module_registration). 149 | The name of the addon is set in the `CMakeLists.txt` using the `add_genepi_library` macro. See [Quick start](#quick-start). 150 | 151 | ```JavaScript 152 | // My JavaScript file 153 | var example = require('my-genepi-addon.node'); 154 | 155 | // Use the binding 156 | ``` 157 | 158 | This `require` will only work if the module can be found by Node.js. To ease the import, you can use the package [bindings](https://www.npmjs.com/package/bindings). It will try several possible paths to find the module. 159 | 160 | ```JavaScript 161 | // My JavaScript file 162 | var example = require('bindings')('my-genepi-addon'); 163 | 164 | // Use the binding 165 | ``` 166 | 167 | 168 | ### Functions 169 | Functions not belonging to any class can be exported inside a named or an anonymous namespace. 170 | The C++ function gets exported to JavaScript with the same name using `GENEPI_FUNCTION`, 171 | or it can be renamed by adding a second argument (without quotation marks) using `NAMED_GENEPI_FUNCTION`. 172 | Addind double underscore in the new name will result in adding the function in nested objects on the js side. 173 | 174 | If the C++ function is overloaded, `GENEPI_MULTIFUNCTION` macro must be used 175 | instead. See [overloaded functions](#overloaded-functions). 176 | 177 | Example from C++: **[`functions.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/functions/functions.cpp)** 178 | 179 | ```C++ 180 | #include 181 | #include 182 | 183 | void sayHello( const std::string& name ) 184 | { 185 | std::cout << "Hello, " << name << std::endl; 186 | } 187 | 188 | void sayBye( const std::string& name ) 189 | { 190 | std::cout << "Bye, " << name << std::endl; 191 | } 192 | 193 | void sayByeAgain( const std::string& name ) 194 | { 195 | std::cout << "Bye again, " << name << std::endl; 196 | } 197 | 198 | namespace foo 199 | { 200 | void sayNamespacedHello( const std::string& name ) 201 | { 202 | std::cout << "Hello, " << name << std::endl; 203 | } 204 | } 205 | 206 | #include 207 | 208 | namespace 209 | { 210 | GENEPI_FUNCTION( sayHello ); 211 | NAMED_GENEPI_FUNCTION( sayBye, sayGoodbye ); 212 | NAMED_GENEPI_FUNCTION( sayByeAgain, say__Goodbye ); 213 | } 214 | 215 | namespace foo 216 | { 217 | GENEPI_FUNCTION( sayNamespacedHello ); 218 | } 219 | 220 | GENEPI_MODULE( functions ); 221 | ``` 222 | 223 | Example from JavaScript: **[`functions.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/functions/functions.js)** 224 | 225 | ```JavaScript 226 | var functions = require('genepi-functions.node'); 227 | 228 | functions.sayHello('you'); // Output: Hello, you 229 | functions.sayGoodbye('you'); // Output: Bye, you 230 | functions.say.Goodbye('you'); // Output: Bye again, you 231 | functions.sayNamespacedHello('you'); // Output: Hello, you 232 | ``` 233 | 234 | ### Overloaded functions 235 | The `GENEPI_FUNCTION()` macro cannot distinguish between several 236 | overloaded versions of the same function, causing an error. 237 | In this case the `GENEPI_MULTIFUNCTION()` macro must be used. 238 | 239 | The second parameter of the macro is the return type. 240 | For calling from JavaScript, each overload needs to have a distinct name, given in the third parameter (without quotation marks). 241 | The remaining parameters are the parameter types of the C++ function. 242 | 243 | Example from C++: **[`overloaded-functions.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/overloaded-functions/overloaded-functions.cpp)** 244 | 245 | ```C++ 246 | #include 247 | #include 248 | 249 | void test( const std::string& number ) 250 | { 251 | std::cout << "Number " << number << std::endl; 252 | } 253 | 254 | void test( int number ) 255 | { 256 | std::cout << "Number " << number << std::endl; 257 | } 258 | 259 | void test( int number, int another_number ) 260 | { 261 | std::cout << "Number " << number + another_number << std::endl; 262 | } 263 | 264 | #include 265 | 266 | namespace 267 | { 268 | GENEPI_MULTIFUNCTION( test, void, test_string, const std::string& ); 269 | GENEPI_MULTIFUNCTION( test, void, test_int, int ); 270 | GENEPI_MULTIFUNCTION( test, void, test_int2, int, int ); 271 | } 272 | 273 | GENEPI_MODULE( overloaded_functions ); 274 | ``` 275 | 276 | Example from JavaScript: **[`overloaded-functions.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/overloaded-functions/overloaded-functions.js)** 277 | 278 | ```JavaScript 279 | var overloadedFunctions = require('genepi-overloaded-functions.node'); 280 | 281 | overloadedFunctions.test_string('42'); // Output: Number 42 282 | overloadedFunctions.test_int(42); // Output: Number 42 283 | overloadedFunctions.test_int2(20, 22); // Output: Number 42 284 | ``` 285 | 286 | ### Classes and constructors 287 | The `GENEPI_CLASS(className)` macro takes the name of your C++ class as an argument 288 | (without any quotation marks), and exports it to JavaScript using the same name. 289 | It's followed by a curly brace enclosed block of method exports, 290 | as if it was a function definition. 291 | 292 | The class can be renamed on the JavaScript side by using the `NAMED_GENEPI_CLASS` macro and passing a string as a 293 | second argument. This is especially useful for binding a template class 294 | specialization with a more reasonable name: `NAMED_GENEPI_CLASS(Data, IntData)`. 295 | 296 | Constructors are exported with a macro call `GENEPI_CONSTRUCTOR(types...);` where `types` is a comma-separated list of arguments to the constructor, such as `int, int`. Calling `GENEPI_CONSTRUCTOR` multiple times allows overloading it. 297 | 298 | Constructor arguments are the only types that `genepi` cannot detect automatically. 299 | 300 | Example from C++: **[`classes.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/classes/classes.cpp)** 301 | 302 | ```C++ 303 | #include 304 | #include 305 | 306 | class ClassExample 307 | { 308 | public: 309 | ClassExample() 310 | { 311 | std::cout << "No arguments" << std::endl; 312 | } 313 | 314 | ClassExample( int a, int b ) 315 | { 316 | std::cout << "Ints: " << a << " " << b << std::endl; 317 | } 318 | 319 | ClassExample( const std::string& msg ) 320 | { 321 | std::cout << "String: " << msg << std::endl; 322 | } 323 | }; 324 | 325 | #include 326 | 327 | GENEPI_CLASS( ClassExample ) 328 | { 329 | GENEPI_CONSTRUCTOR(); 330 | GENEPI_CONSTRUCTOR( int, int ); 331 | GENEPI_CONSTRUCTOR( const std::string& ); 332 | } 333 | 334 | GENEPI_MODULE( classes ); 335 | ``` 336 | 337 | Example from JavaScript: **[`classes.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/classes/classes.js)** 338 | 339 | ```JavaScript 340 | var classes = require('genepi-classes.node'); 341 | 342 | var a = new classes.ClassExample(); // Output: No arguments 343 | var b = new classes.ClassExample(42, 54); // Output: Ints: 42 54 344 | var c = new classes.ClassExample("Don't panic"); // Output: String: Don't panic 345 | ``` 346 | 347 | ### Methods 348 | Methods are exported inside a `GENEPI_CLASS` or a `NAMED_GENEPI_CLASS` block with a macro call `GENEPI_METHOD` 349 | which takes the name of the method as an argument (without any quotation marks). 350 | The C++ method gets exported to JavaScript with the same name. 351 | 352 | If the C++ method is overloaded, `GENEPI_MULTIMETHOD` macro must be used instead. 353 | See [overloaded methods](#overloaded-methods). 354 | 355 | If the method is `static`, it becomes a property of the JavaScript constructor function 356 | and can be accessed like `className.methodName()`. Otherwise it becomes a property of 357 | the prototype and can be accessed like `obj = new className(); obj.methodName();` 358 | 359 | Example from C++: **[`methods.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/methods/methods.cpp)** 360 | 361 | ```C++ 362 | #include 363 | 364 | class MethodExample 365 | { 366 | public: 367 | void add( int a, int b ) 368 | { 369 | sum_ += a + b; 370 | std::cout << "Sum = " << sum_ << std::endl; 371 | } 372 | 373 | static void static_add( int a, int b ) 374 | { 375 | MethodExample example; 376 | example.add( a, b ); 377 | } 378 | 379 | private: 380 | int sum_{ 0 }; 381 | }; 382 | 383 | #include 384 | 385 | GENEPI_CLASS( MethodExample ) 386 | { 387 | GENEPI_CONSTRUCTOR(); 388 | GENEPI_METHOD( add ); 389 | GENEPI_METHOD( static_add ); 390 | } 391 | 392 | GENEPI_MODULE( methods ); 393 | ``` 394 | 395 | Example from JavaScript: **[`methods.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/methods/methods.js)** 396 | 397 | ```JavaScript 398 | 399 | var methods = require('genepi-methods.node'); 400 | 401 | var example = new methods.MethodExample(); 402 | example.add(12, 24); // Output: Sum = 36 403 | 404 | methods.MethodExample.static_add(12,24); // Output: Sum = 36 405 | 406 | ``` 407 | ### Overloaded methods 408 | The `GENEPI_METHOD()` macro, like `GENEPI_FUNCTION` macro, cannot distinguish between several 409 | overloaded versions of the same method. 410 | In this case the `GENEPI_MULTIMETHOD()` macro must be used. 411 | 412 | The second parameter of the macro is the return type. 413 | For calling from JavaScript, each overload needs to have a distinct name, given in the third parameter **(WITH quotation marks)**. 414 | The remaining parameters are the parameter types of the C++ method. 415 | 416 | Example from C++: **[`overloaded-methods.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/overloaded-methods/overloaded-methods.cpp)** 417 | 418 | ```C++ 419 | #include 420 | #include 421 | 422 | class OverloadMethod 423 | { 424 | public: 425 | void test( const std::string& number ) 426 | { 427 | std::cout << "Number " << number << std::endl; 428 | } 429 | 430 | void test( int number ) 431 | { 432 | std::cout << "Number " << number << std::endl; 433 | } 434 | 435 | void test( int number, int another_number ) 436 | { 437 | std::cout << "Number " << number + another_number << std::endl; 438 | } 439 | }; 440 | 441 | #include 442 | 443 | GENEPI_CLASS( OverloadMethod ) 444 | { 445 | GENEPI_CONSTRUCTOR(); 446 | GENEPI_MULTIMETHOD( test, void, "test_string", const std::string& ); 447 | GENEPI_MULTIMETHOD( test, void, "test_int", int ); 448 | GENEPI_MULTIMETHOD( test, void, "test_int2", int, int ); 449 | } 450 | 451 | GENEPI_MODULE( overloaded_methods ); 452 | ``` 453 | 454 | Example from JavaScript: **[`overloaded-functions.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/overloaded-functions/overloaded-functions.js)** 455 | 456 | ```JavaScript 457 | var overloadedMethods = require('genepi-overloaded-methods.node'); 458 | 459 | var a = new overloadedMethods.OverloadMethod(); 460 | a.test_string('42'); // Ouput: Number 42 461 | a.test_int(42); // Ouput: Number 42 462 | a.test_int2(20, 22); // Ouput: Number 42 463 | ``` 464 | 465 | ### Inheritance 466 | When a C++ class inherits another, the `GENEPI_INHERIT` macro can be used to allow calling parent 467 | class methods on the child class, or passing child class instances to C++ methods expecting 468 | parent class instances. 469 | 470 | Internally JavaScript only has prototype-based single inheritance while C++ supports 471 | multiple inheritance. To simulate it, `genepi` will copy the contents of the parents to the prototype. This has otherwise 472 | the same effect, except the JavaScript `instanceof` operator will return `false` for the parent classes. 473 | 474 | Example from C++: **[`inherit.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/inherit/inherit.cpp)** 475 | 476 | ```C++ 477 | #include 478 | 479 | class FirstParent 480 | { 481 | public: 482 | FirstParent() 483 | { 484 | std::cout << "FirstParent" << std::endl; 485 | } 486 | 487 | void from_first_parent() 488 | { 489 | std::cout << "from first parent" << std::endl; 490 | } 491 | }; 492 | 493 | class SecondParent 494 | { 495 | public: 496 | SecondParent() 497 | { 498 | std::cout << "SecondParent" << std::endl; 499 | } 500 | 501 | void from_second_parent() 502 | { 503 | std::cout << "from second parent" << std::endl; 504 | } 505 | }; 506 | 507 | class Child: public FirstParent, public SecondParent 508 | { 509 | public: 510 | Child() 511 | { 512 | std::cout << "Child" << std::endl; 513 | } 514 | }; 515 | 516 | #include 517 | 518 | GENEPI_CLASS( FirstParent ) 519 | { 520 | GENEPI_CONSTRUCTOR(); 521 | GENEPI_METHOD( from_first_parent ); 522 | } 523 | 524 | GENEPI_CLASS( SecondParent ) 525 | { 526 | GENEPI_CONSTRUCTOR(); 527 | GENEPI_METHOD( from_second_parent ); 528 | } 529 | 530 | GENEPI_CLASS( Child ) 531 | { 532 | GENEPI_CONSTRUCTOR(); 533 | GENEPI_INHERIT( FirstParent ); 534 | GENEPI_INHERIT( SecondParent ); 535 | } 536 | 537 | GENEPI_MODULE( inherit ); 538 | ``` 539 | 540 | Example from JavaScript: **[`overloaded-methods.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/overloaded-methods/overloaded-methods.js)** 541 | 542 | ```JavaScript 543 | var inherit = require('genepi-inherit.node'); 544 | 545 | var a = new inherit.Child(); // Ouput: FirstParent / SecondParent / Child 546 | a.from_first_parent(); // Output: from first parent 547 | a.from_second_parent(); // Output: from second parent 548 | ``` 549 | 550 | ### Passing data structures 551 | `genepi` supports automatically converting between JavaScript arrays and C++ 552 | `std::vector` or `std::array` types. Just use them as arguments or return values 553 | in C++ methods. 554 | 555 | Note that data structures don't use the same memory layout in both languages, 556 | so the data always gets copied which takes more time for more data. 557 | For example the strings in an array of strings also get copied, 558 | one character at a time. 559 | 560 | ### Using objects 561 | C++ objects can be passed to and from JavaScript using different 562 | parameter and return types in C++ code: 563 | 564 | - *by reference* using pointers or references 565 | - *by value* 566 | 567 | Constness of objects is **not** ensured by `genepi`. So you could call a non const method on a const object. 568 | 569 | Note: using pointers and references is particularly **dangerous** because the pointer may become invalid without JavaScript noticing it. 570 | 571 | Example from C++: **[`objects.cpp`](https://github.com/Geode-solutions/genepi/blob/master/examples/objects/objects.cpp)** 572 | 573 | ```C++ 574 | #include 575 | 576 | class Coord 577 | { 578 | public: 579 | Coord( int x, int y ) : x_( x ), y_( y ) {} 580 | 581 | int getX() 582 | { 583 | return x_; 584 | } 585 | int getY() 586 | { 587 | return y_; 588 | } 589 | 590 | private: 591 | int x_, y_; 592 | }; 593 | 594 | class ObjectExample 595 | { 596 | public: 597 | static void showByValue( Coord coord ) 598 | { 599 | std::cout << "C++ value " << coord.getX() << ", " << coord.getY() 600 | << std::endl; 601 | } 602 | 603 | static void showByRef( Coord* coord ) 604 | { 605 | std::cout << "C++ ref " << coord->getX() << ", " << coord->getY() 606 | << std::endl; 607 | } 608 | 609 | static Coord getValue() 610 | { 611 | return Coord{ 12, 34 }; 612 | } 613 | 614 | static Coord* getRef() 615 | { 616 | static Coord coord{ 56, 78 }; 617 | return &coord; 618 | } 619 | }; 620 | 621 | #include 622 | 623 | GENEPI_CLASS( Coord ) 624 | { 625 | GENEPI_CONSTRUCTOR( int, int ); 626 | GENEPI_METHOD( getX ); 627 | GENEPI_METHOD( getY ); 628 | } 629 | 630 | GENEPI_CLASS( ObjectExample ) 631 | { 632 | GENEPI_METHOD( showByValue ); 633 | GENEPI_METHOD( showByRef ); 634 | GENEPI_METHOD( getValue ); 635 | GENEPI_METHOD( getRef ); 636 | } 637 | 638 | GENEPI_MODULE( objects ); 639 | ``` 640 | 641 | Example from JavaScript: **[`objects.js`](https://github.com/Geode-solutions/genepi/blob/master/examples/objects/objects.js)** 642 | 643 | ```JavaScript 644 | var objects = require('genepi-objects.node'); 645 | 646 | var value1 = new objects.Coord(123, 456); 647 | var value2 = objects.ObjectExample.getValue(); 648 | objects.ObjectExample.showByValue(value1); // Output: C++ value 123, 456 649 | objects.ObjectExample.showByValue(value2); // Output: C++ value 12, 34 650 | 651 | var ref = objects.ObjectExample.getRef(); 652 | objects.ObjectExample.showByRef(ref); // Output: C++ ref 56, 78 653 | ``` 654 | 655 | ### Type conversion 656 | Parameters and return values of function calls between languages 657 | are automatically converted between equivalent types: 658 | 659 | | JavaScript | C++ | 660 | | ---------- | ------------------------------------------- | 661 | | number | (`un`)`signed char`, `short`, `int`, `long` | 662 | | number | `float`, `double` | 663 | | boolean | `bool` | 664 | | string | `const` (`unsigned`) `char *` | 665 | | string | `std::string` | 666 | | Array | `std::vector` | 667 | | Array | `std::array` | 668 | | genepi-wrapped pointer | Pointer or reference to an instance of any bound class
See [Using objects](#using-objects) | 669 | 670 | ## Alternatives 671 | - [nbind](https://github.com/charto/nbind) 672 | - [Embind](https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html) 673 | - [v8pp](https://github.com/pmed/v8pp) 674 | 675 | 676 | ## Questions 677 | For questions and support please use the official [slack](https://slackin-opengeode.herokuapp.com) and go to the channel #genepi. The issue list of this repo is exclusively for bug reports and feature requests. 678 | 679 | 680 | ## Changelog 681 | Detailed changes for each release are documented in the [release notes](https://github.com/Geode-solutions/OpenGeode/releases). 682 | 683 | 684 | ## License 685 | 686 | [MIT](https://opensource.org/licenses/MIT) 687 | 688 | Copyright (c) 2019-present, Geode-solutions 689 | -------------------------------------------------------------------------------- /cmake/genepiConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019 - 2021 Geode-solutions 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | @PACKAGE_INIT@ 22 | 23 | # Load information for genepi target. 24 | include(${CMAKE_CURRENT_LIST_DIR}/genepi_target.cmake) 25 | 26 | @GENEPI_UTILS@ -------------------------------------------------------------------------------- /cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019 - 2021 Geode-solutions 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | set(CMAKE_CXX_STANDARD 11) 22 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 23 | set(CMAKE_CXX_EXTENSIONS OFF) 24 | 25 | execute_process( 26 | COMMAND node -p "require('node-addon-api').include" 27 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 28 | OUTPUT_VARIABLE NODE_ADDON_API_DIR 29 | ) 30 | string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) 31 | string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) 32 | 33 | macro(add_genepi_library target_name) 34 | add_library(${target_name} SHARED ${ARGN} ${CMAKE_JS_SRC}) 35 | target_include_directories(${target_name} 36 | PUBLIC 37 | ${PROJECT_SOURCE_DIR}/include 38 | ${PROJECT_BINARY_DIR} 39 | PRIVATE 40 | ${NODE_ADDON_API_DIR} 41 | ${CMAKE_JS_INC} 42 | ) 43 | set_target_properties(${target_name} 44 | PROPERTIES 45 | PREFIX "" 46 | SUFFIX ".node" 47 | ) 48 | target_link_libraries(${target_name} 49 | PUBLIC 50 | genepi::genepi 51 | ${CMAKE_JS_LIB} 52 | ) 53 | endmacro() 54 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019 - 2021 Geode-solutions 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | function(add_genepi_example example) 22 | add_genepi_library(genepi-${example} "${CMAKE_CURRENT_LIST_DIR}/${example}/${example}.cpp") 23 | endfunction() 24 | 25 | add_genepi_example(functions) 26 | add_genepi_example(overloaded-functions) 27 | add_genepi_example(classes) 28 | add_genepi_example(methods) 29 | add_genepi_example(overloaded-methods) 30 | add_genepi_example(inherit) 31 | add_genepi_example(objects) 32 | -------------------------------------------------------------------------------- /examples/classes/classes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | class ClassExample 28 | { 29 | public: 30 | ClassExample() 31 | { 32 | std::cout << "No arguments" << std::endl; 33 | } 34 | 35 | ClassExample( int a, int b ) 36 | { 37 | std::cout << "Ints: " << a << " " << b << std::endl; 38 | } 39 | 40 | ClassExample( int a ) 41 | { 42 | std::cout << "Int: " << a << std::endl; 43 | } 44 | 45 | ClassExample( const std::string& msg ) 46 | { 47 | std::cout << "String: " << msg << std::endl; 48 | } 49 | }; 50 | 51 | #include 52 | 53 | GENEPI_CLASS( ClassExample ) 54 | { 55 | GENEPI_CONSTRUCTOR(); 56 | GENEPI_CONSTRUCTOR( int, int ); 57 | GENEPI_CONSTRUCTOR( const std::string& ); 58 | GENEPI_CONSTRUCTOR( int ); 59 | } 60 | 61 | GENEPI_MODULE( classes ); -------------------------------------------------------------------------------- /examples/classes/classes.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var classes = require('bindings')('genepi-classes'); 25 | 26 | var a = new classes.ClassExample(); 27 | var b = new classes.ClassExample(42, 54); 28 | var c = new classes.ClassExample(42); 29 | var d = new classes.ClassExample("Don't panic"); 30 | -------------------------------------------------------------------------------- /examples/functions/functions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | void sayHello( const std::string& name ) 29 | { 30 | std::cout << "Hello, " << name << std::endl; 31 | } 32 | 33 | void sayBye( const std::string& name ) 34 | { 35 | std::cout << "Bye, " << name << std::endl; 36 | } 37 | 38 | void sayBye2( const std::string& name ) 39 | { 40 | std::cout << "Bye2, " << name << std::endl; 41 | } 42 | 43 | void displayArray( std::vector< double > values ) 44 | { 45 | for( const auto i : values ) 46 | { 47 | std::cout << i << ' '; 48 | } 49 | std::cout << std::endl; 50 | } 51 | 52 | void displayArray2( const std::vector< double >& values ) 53 | { 54 | for( const auto i : values ) 55 | { 56 | std::cout << i << ' '; 57 | } 58 | std::cout << std::endl; 59 | } 60 | 61 | namespace foo 62 | { 63 | void sayNamespacedHello( const std::string& name ) 64 | { 65 | std::cout << "Hello, " << name << std::endl; 66 | } 67 | } // namespace foo 68 | 69 | #include 70 | 71 | namespace 72 | { 73 | GENEPI_FUNCTION( sayHello ); 74 | NAMED_GENEPI_FUNCTION( sayBye, sayGoodbye ); 75 | NAMED_GENEPI_FUNCTION( sayBye2, say__Goodbye ); 76 | GENEPI_FUNCTION( displayArray ); 77 | GENEPI_FUNCTION( displayArray2 ); 78 | } // namespace 79 | 80 | namespace foo 81 | { 82 | GENEPI_FUNCTION( sayNamespacedHello ); 83 | } 84 | 85 | GENEPI_MODULE( functions ); -------------------------------------------------------------------------------- /examples/functions/functions.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var functions = require('bindings')('genepi-functions'); 25 | 26 | functions.sayHello('you'); 27 | functions.sayGoodbye('you'); 28 | functions.say.Goodbye('you'); 29 | functions.sayNamespacedHello('you'); 30 | 31 | const array = [1, 2, 3] 32 | functions.displayArray(array) 33 | functions.displayArray2(array) -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | require('./functions/functions') 25 | require('./overloaded-functions/overloaded-functions') 26 | require('./classes/classes') 27 | require('./methods/methods') 28 | require('./overloaded-methods/overloaded-methods') 29 | require('./inherit/inherit') 30 | require('./objects/objects') -------------------------------------------------------------------------------- /examples/inherit/inherit.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | 26 | class FirstParent 27 | { 28 | public: 29 | FirstParent() 30 | { 31 | std::cout << "FirstParent" << std::endl; 32 | } 33 | 34 | void from_first_parent() 35 | { 36 | std::cout << "from first parent" << std::endl; 37 | } 38 | }; 39 | 40 | class SecondParent 41 | { 42 | public: 43 | SecondParent() 44 | { 45 | std::cout << "SecondParent" << std::endl; 46 | } 47 | 48 | void from_second_parent() 49 | { 50 | std::cout << "from second parent" << std::endl; 51 | } 52 | }; 53 | 54 | class Child : public FirstParent, public SecondParent 55 | { 56 | public: 57 | Child() 58 | { 59 | std::cout << "Child" << std::endl; 60 | } 61 | }; 62 | 63 | #include 64 | 65 | GENEPI_CLASS( FirstParent ) 66 | { 67 | GENEPI_CONSTRUCTOR(); 68 | GENEPI_METHOD( from_first_parent ); 69 | } 70 | 71 | GENEPI_CLASS( SecondParent ) 72 | { 73 | GENEPI_CONSTRUCTOR(); 74 | GENEPI_METHOD( from_second_parent ); 75 | } 76 | 77 | GENEPI_CLASS( Child ) 78 | { 79 | GENEPI_CONSTRUCTOR(); 80 | GENEPI_INHERIT( FirstParent ); 81 | GENEPI_INHERIT( SecondParent ); 82 | } 83 | 84 | GENEPI_MODULE( inherit ); -------------------------------------------------------------------------------- /examples/inherit/inherit.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var inherit = require('bindings')('genepi-inherit'); 25 | 26 | var a = new inherit.Child(); 27 | a.from_first_parent(); 28 | a.from_second_parent(); 29 | -------------------------------------------------------------------------------- /examples/methods/methods.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | 26 | class MethodExample 27 | { 28 | public: 29 | void add( int a, int b ) 30 | { 31 | sum_ += a + b; 32 | std::cout << "Sum = " << sum_ << std::endl; 33 | } 34 | 35 | static void static_add( int a, int b ) 36 | { 37 | MethodExample example; 38 | example.add( a, b ); 39 | } 40 | 41 | private: 42 | int sum_{ 0 }; 43 | }; 44 | 45 | #include 46 | 47 | GENEPI_CLASS( MethodExample ) 48 | { 49 | GENEPI_CONSTRUCTOR(); 50 | GENEPI_METHOD( add ); 51 | GENEPI_METHOD( static_add ); 52 | } 53 | 54 | GENEPI_MODULE( methods ); -------------------------------------------------------------------------------- /examples/methods/methods.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var methods = require('bindings')('genepi-methods'); 25 | 26 | var example = new methods.MethodExample(); 27 | example.add(12, 24); 28 | 29 | methods.MethodExample.static_add(12, 24); 30 | -------------------------------------------------------------------------------- /examples/objects/objects.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | 26 | class Coord 27 | { 28 | public: 29 | Coord( int x, int y ) : x_( x ), y_( y ) {} 30 | 31 | int getX() 32 | { 33 | return x_; 34 | } 35 | int getY() 36 | { 37 | return y_; 38 | } 39 | 40 | private: 41 | int x_, y_; 42 | }; 43 | 44 | class ObjectExample 45 | { 46 | public: 47 | static void showByValue( Coord coord ) 48 | { 49 | std::cout << "C++ value " << coord.getX() << ", " << coord.getY() 50 | << std::endl; 51 | } 52 | 53 | static void showByRef( Coord* coord ) 54 | { 55 | std::cout << "C++ ref " << coord->getX() << ", " << coord->getY() 56 | << std::endl; 57 | } 58 | 59 | static Coord getValue() 60 | { 61 | return Coord{ 12, 34 }; 62 | } 63 | 64 | static Coord* getRef() 65 | { 66 | static Coord coord{ 56, 78 }; 67 | return &coord; 68 | } 69 | }; 70 | 71 | #include 72 | 73 | GENEPI_CLASS( Coord ) 74 | { 75 | GENEPI_CONSTRUCTOR( int, int ); 76 | GENEPI_METHOD( getX ); 77 | GENEPI_METHOD( getY ); 78 | } 79 | 80 | GENEPI_CLASS( ObjectExample ) 81 | { 82 | GENEPI_METHOD( showByValue ); 83 | GENEPI_METHOD( showByRef ); 84 | GENEPI_METHOD( getValue ); 85 | GENEPI_METHOD( getRef ); 86 | } 87 | 88 | GENEPI_MODULE( objects ); -------------------------------------------------------------------------------- /examples/objects/objects.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var objects = require('bindings')('genepi-objects'); 25 | 26 | var value1 = new objects.Coord(123, 456); 27 | var value2 = objects.ObjectExample.getValue(); 28 | objects.ObjectExample.showByValue(value1); 29 | objects.ObjectExample.showByValue(value2); 30 | 31 | var ref = objects.ObjectExample.getRef(); 32 | objects.ObjectExample.showByRef(ref); 33 | -------------------------------------------------------------------------------- /examples/overloaded-functions/overloaded-functions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | void test( const std::string& number ) 28 | { 29 | std::cout << "Number " << number << std::endl; 30 | } 31 | 32 | void test( int number ) 33 | { 34 | std::cout << "Number " << number << std::endl; 35 | } 36 | 37 | void test( int number, int another_number ) 38 | { 39 | std::cout << "Number " << number + another_number << std::endl; 40 | } 41 | 42 | #include 43 | 44 | namespace 45 | { 46 | GENEPI_MULTIFUNCTION( test, void, test_string, const std::string& ); 47 | GENEPI_MULTIFUNCTION( test, void, test_int, int ); 48 | GENEPI_MULTIFUNCTION( test, void, test_int2, int, int ); 49 | } // namespace 50 | 51 | GENEPI_MODULE( overloaded_functions ); 52 | -------------------------------------------------------------------------------- /examples/overloaded-functions/overloaded-functions.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var overloadedFunctions = require('bindings')('genepi-overloaded-functions'); 25 | 26 | overloadedFunctions.test_string('42'); 27 | overloadedFunctions.test_int(42); 28 | overloadedFunctions.test_int2(20, 22); -------------------------------------------------------------------------------- /examples/overloaded-methods/overloaded-methods.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | class OverloadMethod 28 | { 29 | public: 30 | void test( const std::string& number ) 31 | { 32 | std::cout << "Number " << number << std::endl; 33 | } 34 | 35 | void test( int number ) 36 | { 37 | std::cout << "Number " << number << std::endl; 38 | } 39 | 40 | void test( int number, int another_number ) 41 | { 42 | std::cout << "Number " << number + another_number << std::endl; 43 | } 44 | }; 45 | 46 | #include 47 | 48 | GENEPI_CLASS( OverloadMethod ) 49 | { 50 | GENEPI_CONSTRUCTOR(); 51 | GENEPI_MULTIMETHOD( test, void, "test_string", const std::string& ); 52 | GENEPI_MULTIMETHOD( test, void, "test_int", int ); 53 | GENEPI_MULTIMETHOD( test, void, "test_int2", int, int ); 54 | } 55 | 56 | GENEPI_MODULE( overloaded_methods ); 57 | -------------------------------------------------------------------------------- /examples/overloaded-methods/overloaded-methods.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | var overloadedMethods = require('bindings')('genepi-overloaded-methods'); 25 | 26 | var a = new overloadedMethods.OverloadMethod(); 27 | a.test_string('42'); 28 | a.test_int(42); 29 | a.test_int2(20, 22); -------------------------------------------------------------------------------- /include/genepi/arg_from_napi_value.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | namespace genepi 29 | { 30 | // ArgFromNapiValue converts JavaScript types into C++ types, usually with 31 | // BindingType<>::fromNapiValueType but some types require additional 32 | // temporary storage, such as a string converted to C style. FromNapiValue 33 | // is a struct, so wrappers for all objects can be constructed as function 34 | // arguments, and their actual values passed to the called function are 35 | // returned by the get() function. The wrappers go out of scope and are 36 | // destroyed at the end of the function call. 37 | 38 | // Handle most C++ types. 39 | template < size_t Index, typename ArgType > 40 | struct ArgFromNapiValue 41 | { 42 | using Transformed = TypeTransformer< ArgType >; 43 | 44 | ArgFromNapiValue( const Napi::CallbackInfo &args ) {} 45 | 46 | typename Transformed::Type get( const Napi::CallbackInfo &args ) 47 | { 48 | return Transformed::Binding::fromNapiValue( args[Index] ); 49 | } 50 | }; 51 | 52 | // Handle char pointers, which will receive a C string representation of any 53 | // JavaScript value. 54 | template < size_t Index > 55 | struct ArgFromNapiValue< Index, const char * > 56 | { 57 | ArgFromNapiValue( const Napi::CallbackInfo &args ) 58 | : val( args[Index].ToString() ) 59 | { 60 | } 61 | 62 | const char *get( const Napi::CallbackInfo &args ) 63 | { 64 | return val.Utf8Value().c_str(); 65 | } 66 | 67 | // RAII style storage for the string data. 68 | Napi::String val; 69 | }; 70 | 71 | // Automatically cast char to unsigned if the C++ function expects it. 72 | template < size_t Index > 73 | struct ArgFromNapiValue< Index, const unsigned char * > 74 | { 75 | ArgFromNapiValue( const Napi::CallbackInfo &args ) 76 | : val( args[Index].ToString() ) 77 | { 78 | } 79 | 80 | const unsigned char *get( const Napi::CallbackInfo &args ) 81 | { 82 | return reinterpret_cast< const unsigned char * >( 83 | val.Utf8Value().c_str() ); 84 | } 85 | 86 | // RAII style storage for the string data. 87 | Napi::String val; 88 | }; 89 | } // namespace genepi 90 | -------------------------------------------------------------------------------- /include/genepi/bind_class.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | namespace genepi 32 | { 33 | template < typename Bound > 34 | class BindClass : public BindClassBase 35 | { 36 | public: 37 | void init( std::string name ) 38 | { 39 | this->name_ = std::move( name ); 40 | } 41 | 42 | static BindClass& instance() 43 | { 44 | return Singleton::instance< BindClass< Bound > >(); 45 | } 46 | 47 | std::string type() final 48 | { 49 | return typeid( Bound ).name(); 50 | } 51 | 52 | template < typename SuperType > 53 | void add_super_class(); 54 | 55 | void initialize( Napi::Env& env, Napi::Object& target ) final 56 | { 57 | std::deque< MethodDefinition > methods; 58 | std::unordered_set< const BindClassBase* > classes; 59 | initialize_api( methods, classes ); 60 | 61 | ClassWrapperBase< Bound >::instance().Initialize( 62 | env, target, name_, static_methods_, methods, instance() ); 63 | } 64 | 65 | void construct( const Napi::CallbackInfo& info ) const 66 | { 67 | try 68 | { 69 | for( const auto& constructor : constructors_.at( 70 | static_cast< unsigned int >( info.Length() ) ) ) 71 | { 72 | try 73 | { 74 | constructor( info ); 75 | return; 76 | } 77 | catch( const Napi::Error& /*unsued*/ ) 78 | { 79 | continue; 80 | } 81 | } 82 | throw Napi::Error::New( info.Env(), "Wrong argument types" ); 83 | } 84 | catch( const std::out_of_range& ) 85 | { 86 | throw Napi::Error::New( 87 | info.Env(), "Wrong number of arguments" ); 88 | } 89 | } 90 | }; 91 | 92 | template < class Bound > 93 | ClassWrapper< Bound >::ClassWrapper( const Napi::CallbackInfo& info ) 94 | : Napi::ObjectWrap< ClassWrapper< Bound > >( info ) 95 | { 96 | if( info.Length() == 2 && info[0].IsBoolean() && info[1].IsExternal() ) 97 | { 98 | if( info[0].As< Napi::Boolean >() ) 99 | { 100 | this->underlying_class_ = 101 | *info[1] 102 | .As< Napi::External< std::shared_ptr< Bound > > >() 103 | .Data(); 104 | } 105 | else 106 | { 107 | this->underlying_class_.reset( 108 | info[1].As< Napi::External< Bound > >().Data(), 109 | NoDeleter{} ); 110 | } 111 | } 112 | else 113 | { 114 | BindClass< Bound >::instance().construct( info ); 115 | } 116 | } 117 | 118 | template < class Bound, class SuperType > 119 | void* upcast( void* arg ) 120 | { 121 | return static_cast< SuperType* >( static_cast< Bound* >( arg ) ); 122 | } 123 | 124 | template < class Bound > 125 | template < typename SuperType > 126 | void BindClass< Bound >::add_super_class() 127 | { 128 | super_classes_.emplace_back( 129 | BindClass< SuperType >::instance(), upcast< Bound, SuperType > ); 130 | } 131 | 132 | } // namespace genepi 133 | -------------------------------------------------------------------------------- /include/genepi/bind_class_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace genepi 36 | { 37 | class BindClassBase; 38 | } // namespace genepi 39 | 40 | namespace genepi 41 | { 42 | using Upcast = std::add_pointer< void*( void* ) >::type; 43 | 44 | struct SuperClassSpec 45 | { 46 | SuperClassSpec( BindClassBase& superClass, Upcast upcast ) 47 | : superClass( superClass ), upcast( upcast ) 48 | { 49 | } 50 | 51 | BindClassBase& superClass; 52 | Upcast upcast; 53 | }; 54 | 55 | class BindClassBase : public Singleton 56 | { 57 | public: 58 | void add_constructor( BaseSignature* signature ) 59 | { 60 | constructors_[signature->arity()].emplace_back( 61 | signature->caller() ); 62 | } 63 | 64 | void add_static_method( 65 | std::string name, BaseSignature* signature, unsigned int number ) 66 | { 67 | static_methods_.emplace_back( 68 | std::move( name ), number, signature ); 69 | } 70 | 71 | void add_method( 72 | std::string name, BaseSignature* signature, unsigned int number ) 73 | { 74 | methods_.emplace_back( std::move( name ), number, signature ); 75 | } 76 | 77 | void* upcastStep( BindClassBase& dst, void* ptr ) 78 | { 79 | if( &dst == this ) 80 | { 81 | return ptr; 82 | } 83 | 84 | for( auto& spec : super_classes_ ) 85 | { 86 | void* superPtr = 87 | spec.superClass.upcastStep( dst, spec.upcast( ptr ) ); 88 | if( superPtr ) 89 | { 90 | return superPtr; 91 | } 92 | } 93 | 94 | return nullptr; 95 | } 96 | 97 | virtual void initialize( Napi::Env& env, Napi::Object& target ) = 0; 98 | 99 | virtual std::string type() = 0; 100 | 101 | protected: 102 | void get_methods( std::deque< MethodDefinition >& methods ) const 103 | { 104 | for( const auto& method : methods_ ) 105 | { 106 | methods.push_back( method ); 107 | } 108 | } 109 | 110 | void initialize_api( std::deque< MethodDefinition >& methods, 111 | std::unordered_set< const BindClassBase* >& classes ) const 112 | { 113 | if( !classes.insert( this ).second ) 114 | { 115 | return; 116 | } 117 | get_methods( methods ); 118 | for( const auto& spec : super_classes_ ) 119 | { 120 | spec.superClass.initialize_api( methods, classes ); 121 | } 122 | } 123 | 124 | protected: 125 | std::string name_; 126 | std::map< unsigned int, std::vector< Callable > > constructors_; 127 | std::deque< MethodDefinition > static_methods_; 128 | std::deque< MethodDefinition > methods_; 129 | std::deque< SuperClassSpec > super_classes_; 130 | }; 131 | } // namespace genepi 132 | -------------------------------------------------------------------------------- /include/genepi/binding_std.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace genepi 33 | { 34 | // Array. 35 | template < typename ArgType, size_t size > 36 | struct BindingType< std::array< ArgType, size > > 37 | { 38 | using Type = std::array< ArgType, size >; 39 | 40 | static bool checkType( Napi::Value arg ) 41 | { 42 | if( !arg.IsArray() ) 43 | { 44 | return false; 45 | } 46 | return arg.As< Napi::Array >().Length() >= size; 47 | } 48 | 49 | static Type fromNapiValue( Napi::Value arg ) 50 | { 51 | // TODO: Don't convert sparse arrays. 52 | auto array = arg.ToObject(); 53 | Type val; 54 | for( uint32_t number = 0; number < size; ++number ) 55 | { 56 | if( BindingType< ArgType >::checkType( array[number] ) ) 57 | { 58 | val[number] = 59 | convertFromNapiValue< ArgType >( array[number] ); 60 | } 61 | else 62 | { 63 | throw( std::runtime_error( 64 | "Error converting array element" ) ); 65 | } 66 | } 67 | return val; 68 | } 69 | 70 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 71 | { 72 | auto array = Napi::Array::New( env, size ); 73 | for( uint32_t number = 0; number < size; ++number ) 74 | { 75 | array.Set( 76 | number, convertToNapiValue( 77 | env, std::forward< ArgType >( arg[number] ) ) ); 78 | } 79 | return array; 80 | } 81 | }; 82 | 83 | template < typename ArgType, size_t size > 84 | struct BindingType< const std::array< ArgType, size > & > 85 | { 86 | using Type = std::array< ArgType, size >; 87 | 88 | static bool checkType( Napi::Value arg ) 89 | { 90 | return arg.IsArray(); 91 | } 92 | 93 | static Type fromNapiValue( Napi::Value arg ) 94 | { 95 | return BindingType< Type >::fromNapiValue( arg ); 96 | } 97 | 98 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 99 | { 100 | return BindingType< Type >::toNapiValue( env, arg ); 101 | } 102 | }; 103 | 104 | // Vector. 105 | template < typename ArgType > 106 | struct BindingType< std::vector< ArgType > > 107 | { 108 | using Type = std::vector< ArgType >; 109 | 110 | static bool checkType( Napi::Value arg ) 111 | { 112 | return arg.IsArray(); 113 | } 114 | 115 | static Type fromNapiValue( Napi::Value arg ) 116 | { 117 | // TODO: Don't convert sparse arrays. 118 | auto array = arg.As< Napi::Array >(); 119 | uint32_t count = array.Length(); 120 | Type val; 121 | val.reserve( count ); 122 | for( uint32_t number = 0; number < count; ++number ) 123 | { 124 | if( BindingType< ArgType >::checkType( array[number] ) ) 125 | { 126 | val.push_back( 127 | convertFromNapiValue< ArgType >( array[number] ) ); 128 | } 129 | else 130 | { 131 | throw( std::runtime_error( 132 | "Error converting array element" ) ); 133 | } 134 | } 135 | return val; 136 | } 137 | 138 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 139 | { 140 | uint32_t count = arg.size(); 141 | auto array = Napi::Array::New( env, count ); 142 | for( uint32_t number = 0; number < count; ++number ) 143 | { 144 | array.Set( 145 | number, convertToNapiValue( 146 | env, std::forward< ArgType >( arg[number] ) ) ); 147 | } 148 | return array; 149 | } 150 | }; 151 | 152 | template < typename ArgType > 153 | struct BindingType< const std::vector< ArgType > & > 154 | { 155 | using Type = std::vector< ArgType >; 156 | 157 | static bool checkType( Napi::Value arg ) 158 | { 159 | return arg.IsArray(); 160 | } 161 | 162 | static Type fromNapiValue( Napi::Value arg ) 163 | { 164 | return BindingType< Type >::fromNapiValue( arg ); 165 | } 166 | 167 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 168 | { 169 | return BindingType< Type >::toNapiValue( env, arg ); 170 | } 171 | }; 172 | 173 | // String. 174 | template <> 175 | struct BindingType< std::string > 176 | { 177 | using Type = std::string; 178 | 179 | static bool checkType( Napi::Value arg ) 180 | { 181 | return arg.IsString(); 182 | } 183 | 184 | static Type fromNapiValue( Napi::Value arg ) 185 | { 186 | return arg.ToString().Utf8Value(); 187 | } 188 | 189 | static Napi::Value toNapiValue( Napi::Env env, Type arg ) 190 | { 191 | return Napi::String::New( env, arg ); 192 | } 193 | }; 194 | 195 | // String reference. 196 | template <> 197 | struct BindingType< const std::string & > 198 | { 199 | using Type = std::string; 200 | 201 | static bool checkType( Napi::Value arg ) 202 | { 203 | return arg.IsString(); 204 | } 205 | 206 | static Type fromNapiValue( Napi::Value arg ) 207 | { 208 | return arg.ToString().Utf8Value(); 209 | } 210 | 211 | static Napi::Value toNapiValue( Napi::Env env, Type arg ) 212 | { 213 | return Napi::String::New( env, arg ); 214 | } 215 | }; 216 | 217 | template < size_t Index > 218 | struct ArgFromNapiValue< Index, const std::string & > 219 | { 220 | // TODO: Get string length from JS to support zero bytes? 221 | ArgFromNapiValue( const Napi::CallbackInfo &args ) 222 | : val( args[Index].ToString().Utf8Value() ) 223 | { 224 | } 225 | 226 | const std::string &get( const Napi::CallbackInfo &args ) 227 | { 228 | return val; 229 | } 230 | 231 | // RAII style storage for the string data. 232 | std::string val; 233 | }; 234 | } // namespace genepi 235 | -------------------------------------------------------------------------------- /include/genepi/binding_type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | namespace genepi 35 | { 36 | // Generic C++ object. 37 | template < typename ArgType > 38 | struct BindingType 39 | { 40 | using Type = ArgType; 41 | 42 | static bool checkType( Napi::Value arg ) 43 | { 44 | return BindingType< Type * >::checkType( arg ); 45 | } 46 | 47 | static Type fromNapiValue( Napi::Value arg ) 48 | { 49 | return *BindingType< Type * >::fromNapiValue( arg ); 50 | } 51 | 52 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 53 | { 54 | return BindingType< std::unique_ptr< Type > >::toNapiValue( env, 55 | // Move construct from stack to heap. 56 | std::unique_ptr< Type >{ new Type{ std::move( arg ) } } ); 57 | } 58 | }; 59 | 60 | // Object pointer. 61 | template < typename ArgType > 62 | struct BindingType< ArgType * > 63 | { 64 | using Type = ArgType *; 65 | using BaseType = typename std::remove_const< ArgType >::type; 66 | 67 | static bool checkType( Napi::Value arg ) 68 | { 69 | return arg.IsObject(); 70 | } 71 | 72 | static Type fromNapiValue( Napi::Value arg ) 73 | { 74 | return ClassWrapperBase< BaseType >::get_bound( arg ); 75 | } 76 | 77 | template < typename T = ArgType > 78 | static typename std::enable_if< std::is_move_constructible< T >::value, 79 | Napi::Value >::type 80 | toNapiValue( Napi::Env env, Type arg ) 81 | { 82 | if( std::find_if( class_list().begin(), class_list().end(), 83 | []( BindClassBase *bind_class ) { 84 | return bind_class->type() 85 | == BindClass< ArgType >::instance().type(); 86 | } ) 87 | != class_list().end() ) 88 | { 89 | return ClassWrapperBase< BaseType >::instance().create( 90 | env, { Napi::Boolean::New( env, false ), 91 | Napi::External< BaseType >::New( 92 | env, const_cast< BaseType * >( arg ) ) } ); 93 | } 94 | else 95 | { 96 | return BindingType< BaseType >::toNapiValue( 97 | env, std::move( *const_cast< BaseType * >( arg ) ) ); 98 | } 99 | } 100 | 101 | template < typename T = ArgType > 102 | static typename std::enable_if< !std::is_move_constructible< T >::value, 103 | Napi::Value >::type 104 | toNapiValue( Napi::Env env, Type arg ) 105 | { 106 | return ClassWrapperBase< BaseType >::instance().create( 107 | env, { Napi::Boolean::New( env, false ), 108 | Napi::External< BaseType >::New( 109 | env, const_cast< BaseType * >( arg ) ) } ); 110 | } 111 | }; 112 | 113 | // Object reference. 114 | template < typename ArgType > 115 | struct BindingType< ArgType & > 116 | { 117 | using Type = ArgType &; 118 | 119 | static bool checkType( Napi::Value arg ) 120 | { 121 | return arg.IsObject(); 122 | } 123 | 124 | static Type fromNapiValue( Napi::Value arg ) 125 | { 126 | return *BindingType< ArgType * >::fromNapiValue( arg ); 127 | } 128 | 129 | static Napi::Value toNapiValue( Napi::Env env, Type arg ) 130 | { 131 | return BindingType< ArgType * >::toNapiValue( env, &arg ); 132 | } 133 | }; 134 | 135 | template < typename ArgType > 136 | struct BindingType< std::unique_ptr< ArgType > > 137 | { 138 | using Type = std::unique_ptr< ArgType >; 139 | using BaseType = typename std::remove_const< ArgType >::type; 140 | 141 | // checkType and fromNapiValue not supported! C++ objects are wrapped in 142 | // shared_ptr which would become invalid if passed back as unique_ptr. 143 | 144 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 145 | { 146 | return BindingType< ArgType * >::toNapiValue( env, arg.release() ); 147 | } 148 | }; 149 | 150 | template < typename ArgType > 151 | struct BindingType< std::shared_ptr< ArgType > > 152 | { 153 | using Type = std::shared_ptr< ArgType >; 154 | using BaseType = typename std::remove_const< ArgType >::type; 155 | 156 | static bool checkType( Napi::Value arg ) 157 | { 158 | return arg.IsObject(); 159 | } 160 | 161 | static Type fromNapiValue( Napi::Value arg ) 162 | { 163 | return ClassWrapperBase< ArgType >::get_smartpointer( arg ); 164 | } 165 | 166 | static Napi::Value toNapiValue( Napi::Env env, Type &&arg ) 167 | { 168 | return ClassWrapperBase< BaseType >::instance().create( 169 | env, { Napi::Boolean::New( env, true ), 170 | Napi::External< std::shared_ptr< ArgType > >::New( 171 | env, new std::shared_ptr< ArgType >{ 172 | std::move( arg ) } ) } ); 173 | } 174 | }; 175 | 176 | // Numeric and boolean types. 177 | // The static cast silences a compiler warning in Visual Studio. 178 | 179 | #define DEFINE_NATIVE_BINDING_TYPE( ArgType, checker, cast, decode, jsClass ) \ 180 | template <> \ 181 | struct BindingType< ArgType > \ 182 | { \ 183 | using Type = ArgType; \ 184 | \ 185 | static bool checkType( Napi::Value arg ) \ 186 | { \ 187 | return arg.checker(); \ 188 | } \ 189 | \ 190 | static Type fromNapiValue( Napi::Value arg ) \ 191 | { \ 192 | return static_cast< Type >( arg.cast().decode() ); \ 193 | } \ 194 | \ 195 | static Napi::Value toNapiValue( Napi::Env env, Type arg ) \ 196 | { \ 197 | return jsClass::New( env, arg ); \ 198 | } \ 199 | } 200 | 201 | DEFINE_NATIVE_BINDING_TYPE( 202 | bool, IsBoolean, ToBoolean, Value, Napi::Boolean ); 203 | 204 | DEFINE_NATIVE_BINDING_TYPE( 205 | double, IsNumber, ToNumber, DoubleValue, Napi::Number ); 206 | DEFINE_NATIVE_BINDING_TYPE( 207 | float, IsNumber, ToNumber, FloatValue, Napi::Number ); 208 | 209 | DEFINE_NATIVE_BINDING_TYPE( 210 | unsigned int, IsNumber, ToNumber, Uint32Value, Napi::Number ); 211 | DEFINE_NATIVE_BINDING_TYPE( 212 | unsigned short, IsNumber, ToNumber, Uint32Value, Napi::Number ); 213 | DEFINE_NATIVE_BINDING_TYPE( 214 | unsigned char, IsNumber, ToNumber, Uint32Value, Napi::Number ); 215 | 216 | DEFINE_NATIVE_BINDING_TYPE( 217 | signed int, IsNumber, ToNumber, Int32Value, Napi::Number ); 218 | DEFINE_NATIVE_BINDING_TYPE( 219 | signed short, IsNumber, ToNumber, Int32Value, Napi::Number ); 220 | DEFINE_NATIVE_BINDING_TYPE( 221 | signed char, IsNumber, ToNumber, Int32Value, Napi::Number ); 222 | 223 | DEFINE_NATIVE_BINDING_TYPE( 224 | char, IsNumber, ToNumber, Int32Value, Napi::Number ); 225 | 226 | #define DEFINE_STRING_BINDING_TYPE( ArgType ) \ 227 | template <> \ 228 | struct BindingType< ArgType > \ 229 | { \ 230 | using Type = ArgType; \ 231 | \ 232 | static bool checkType( Napi::Value arg ) \ 233 | { \ 234 | return arg.IsString(); \ 235 | } \ 236 | \ 237 | static Napi::Value toNapiValue( Napi::Env env, Type arg ) \ 238 | { \ 239 | const char *buf = ( arg == nullptr ) \ 240 | ? "" \ 241 | : reinterpret_cast< const char * >( arg ); \ 242 | return Napi::String::New( env, buf, strlen( buf ) ); \ 243 | } \ 244 | } 245 | 246 | DEFINE_STRING_BINDING_TYPE( unsigned char * ); 247 | DEFINE_STRING_BINDING_TYPE( char * ); 248 | DEFINE_STRING_BINDING_TYPE( const unsigned char * ); 249 | DEFINE_STRING_BINDING_TYPE( const char * ); 250 | 251 | // void return values are passed to toNapiValue as null pointers. 252 | template <> 253 | struct BindingType< void > 254 | { 255 | using Type = std::nullptr_t; 256 | 257 | static Type fromNapiValue( Napi::Value arg ) 258 | { 259 | return nullptr; 260 | } 261 | 262 | static Napi::Value toNapiValue( Napi::Env env, Type arg ) 263 | { 264 | return env.Undefined(); 265 | } 266 | }; 267 | } // namespace genepi 268 | -------------------------------------------------------------------------------- /include/genepi/callable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | namespace genepi 29 | { 30 | using Callable = 31 | std::add_pointer< Napi::Value( const Napi::CallbackInfo& ) >::type; 32 | } // namespace genepi 33 | -------------------------------------------------------------------------------- /include/genepi/caller.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | namespace genepi 30 | { 31 | // Caller handles the template magic to compose a method call from a class 32 | // and parts of a method signature extracted from it. 33 | 34 | template < typename ReturnType, typename ArgList > 35 | struct Caller; 36 | 37 | template < typename ReturnType, typename... Args > 38 | struct Caller< ReturnType, TypeList< Args... > > 39 | { 40 | template < class Bound, typename MethodType > 41 | static Napi::Value call_method( 42 | Bound &target, MethodType method, const Napi::CallbackInfo &args ) 43 | { 44 | return convertToNapiValue< ReturnType >( 45 | args.Env(), ( target.*method )( Args( args ).get( args )... ) ); 46 | } 47 | 48 | template < typename Function > 49 | static Napi::Value call_function( 50 | Function func, const Napi::CallbackInfo &args ) 51 | { 52 | return convertToNapiValue< ReturnType >( 53 | args.Env(), ( *func )( Args( args ).get( args )... ) ); 54 | } 55 | }; 56 | 57 | // Specialize Caller for void return type, because toNapiValueType needs a 58 | // non-void argument. 59 | template < typename... Args > 60 | struct Caller< void, TypeList< Args... > > 61 | { 62 | template < class Bound, typename MethodType > 63 | static Napi::Value call_method( 64 | Bound &target, MethodType method, const Napi::CallbackInfo &args ) 65 | { 66 | ( target.*method )( Args( args ).get( args )... ); 67 | return args.Env().Undefined(); 68 | } 69 | 70 | template < typename Function > 71 | static Napi::Value call_function( 72 | Function func, const Napi::CallbackInfo &args ) 73 | { 74 | ( *func )( Args( args ).get( args )... ); 75 | return args.Env().Undefined(); 76 | } 77 | }; 78 | } // namespace genepi 79 | -------------------------------------------------------------------------------- /include/genepi/checker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | namespace genepi 30 | { 31 | // CheckNapiValue verifies if the type of a JavaScript handle corresponds to 32 | // a C++ type. 33 | template < size_t Index, typename ArgType > 34 | struct CheckNapiValue 35 | { 36 | using Transformed = TypeTransformer< ArgType >; 37 | 38 | static bool checkType( const Napi::CallbackInfo &args ) 39 | { 40 | return Transformed::Binding::checkType( args[Index] ); 41 | } 42 | }; 43 | 44 | template < typename ArgList > 45 | struct Checker; 46 | 47 | template < typename... Args > 48 | struct Checker< TypeList< Args... > > 49 | { 50 | static bool booleanAnd( bool flag ) 51 | { 52 | return flag; 53 | } 54 | 55 | template < typename... Rest > 56 | static bool booleanAnd( bool flag, Rest... rest ) 57 | { 58 | return flag & booleanAnd( rest... ); 59 | } 60 | 61 | static bool are_types_valid( const Napi::CallbackInfo &args ) 62 | { 63 | return booleanAnd( Args::checkType( args )..., true ); 64 | } 65 | 66 | static std::string getTypeError( const Napi::CallbackInfo &args ) 67 | { 68 | std::vector< bool > flagList{ Args::checkType( args )..., true }; 69 | std::string error( "Type mismatch:" ); 70 | for( auto flag : flagList ) 71 | { 72 | error += " " + std::to_string( flag ); 73 | } 74 | return error; 75 | } 76 | }; 77 | } // namespace genepi 78 | -------------------------------------------------------------------------------- /include/genepi/class_definer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace genepi 33 | { 34 | template < typename Bound > 35 | class ClassDefiner 36 | { 37 | public: 38 | ClassDefiner( std::string name ) 39 | : bindClass( BindClass< Bound >::instance() ) 40 | { 41 | bindClass.init( std::move( name ) ); 42 | register_class( bindClass ); 43 | } 44 | 45 | template < typename... Args > 46 | void add_constructor() 47 | { 48 | bindClass.add_constructor( 49 | &ConstructorSignature< Bound, Args... >::instance() ); 50 | } 51 | 52 | template < typename ReturnType, typename... Args > 53 | void add_method( std::string name, 54 | ReturnType ( *function )( Args... ), 55 | std::string bounded_name = std::string{} ) 56 | { 57 | using Signature = FunctionSignature< decltype( function ), 58 | std::nullptr_t, ReturnType, Args... >; 59 | if( bounded_name.empty() ) 60 | { 61 | bounded_name = std::move( name ); 62 | } 63 | bindClass.add_static_method( std::move( bounded_name ), 64 | &Signature::instance(), Signature::add_method( function ) ); 65 | } 66 | 67 | template < typename ReturnType, typename... Args > 68 | void add_method( std::string name, 69 | ReturnType ( Bound::*method )( Args... ), 70 | std::string bounded_name = std::string{} ) 71 | { 72 | using Signature = MethodSignature< decltype( method ), Bound, 73 | ReturnType, Args... >; 74 | if( bounded_name.empty() ) 75 | { 76 | bounded_name = std::move( name ); 77 | } 78 | bindClass.add_method( std::move( bounded_name ), 79 | &Signature::instance(), Signature::add_method( method ) ); 80 | } 81 | 82 | template < typename ReturnType, typename... Args > 83 | void add_method( std::string name, 84 | ReturnType ( Bound::*method )( Args... ) const, 85 | std::string bounded_name = std::string{} ) 86 | { 87 | using Signature = MethodSignature< decltype( method ), Bound, 88 | ReturnType, Args... >; 89 | if( bounded_name.empty() ) 90 | { 91 | bounded_name = std::move( name ); 92 | } 93 | bindClass.add_method( std::move( bounded_name ), 94 | &Signature::instance(), Signature::add_method( method ) ); 95 | } 96 | 97 | template < typename ReturnType, typename... Args > 98 | struct Overloaded 99 | { 100 | Overloaded( ClassDefiner& definer ) : definer_( definer ) {} 101 | 102 | void add_method( std::string name, 103 | ReturnType ( *function )( Args... ), 104 | std::string bounded_name ) 105 | { 106 | definer_.add_method( 107 | std::move( name ), function, std::move( bounded_name ) ); 108 | } 109 | 110 | void add_method( std::string name, 111 | ReturnType ( Bound::*method )( Args... ), 112 | std::string bounded_name ) 113 | { 114 | definer_.add_method( 115 | std::move( name ), method, std::move( bounded_name ) ); 116 | } 117 | 118 | void add_method( std::string name, 119 | ReturnType ( Bound::*method )( Args... ) const, 120 | std::string bounded_name ) 121 | { 122 | definer_.add_method( 123 | std::move( name ), method, std::move( bounded_name ) ); 124 | } 125 | 126 | ClassDefiner& definer_; 127 | }; 128 | 129 | template < typename ReturnType, typename... Args > 130 | Overloaded< ReturnType, Args... > overloaded() 131 | { 132 | return { *this }; 133 | } 134 | 135 | template < class SuperType > 136 | void add_inherit() 137 | { 138 | bindClass.template add_super_class< SuperType >(); 139 | } 140 | 141 | private: 142 | BindClass< Bound >& bindClass; 143 | }; 144 | } // namespace genepi 145 | -------------------------------------------------------------------------------- /include/genepi/class_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | namespace genepi 35 | { 36 | template < class Bound > 37 | class ClassWrapper; 38 | 39 | template < class Bound > 40 | class ClassWrapperBase : public Singleton 41 | { 42 | public: 43 | using WrapperBase = ClassWrapperBase< Bound >; 44 | using Wrapper = ClassWrapper< Bound >; 45 | using Descriptor = typename Napi::ObjectWrap< 46 | ClassWrapper< Bound > >::PropertyDescriptor; 47 | 48 | Napi::Object create( 49 | Napi::Env env, const std::vector< napi_value >& args ) 50 | { 51 | Napi::EscapableHandleScope scope( env ); 52 | return scope.Escape( constructor_.New( args ) ).ToObject(); 53 | } 54 | 55 | static WrapperBase& instance() 56 | { 57 | return Singleton::instance< WrapperBase >(); 58 | } 59 | 60 | template < typename... Args > 61 | static void create_obj( const Napi::CallbackInfo& info, Args&&... args ) 62 | { 63 | WrapperBase::get_smartpointer( info.This() ) 64 | .reset( new Bound{ args... } ); 65 | } 66 | 67 | static Bound* get_bound( const Napi::CallbackInfo& info ) 68 | { 69 | Bound* ptr = WrapperBase::get_smartpointer( info.This() ).get(); 70 | BindClassBase* dst = ClassWrapper< Bound >::instance().bind_class_; 71 | BindClassBase* src = SignatureParam::get( info )->bind_class; 72 | 73 | if( &dst == &src ) 74 | { 75 | return ptr; 76 | } 77 | 78 | return static_cast< Bound* >( src->upcastStep( *dst, ptr ) ); 79 | } 80 | 81 | static Bound* get_bound( const Napi::Value& arg ) 82 | { 83 | return WrapperBase::get_smartpointer( arg ).get(); 84 | } 85 | 86 | static std::shared_ptr< Bound >& get_smartpointer( 87 | const Napi::Value& value ) 88 | { 89 | return Wrapper::Unwrap( value.ToObject() )->underlying_class_; 90 | } 91 | 92 | void Initialize( Napi::Env& env, 93 | Napi::Object& target, 94 | const std::string& name, 95 | const std::deque< MethodDefinition >& static_methodList, 96 | const std::deque< MethodDefinition >& methodList, 97 | BindClassBase& bind_class ) 98 | { 99 | bind_class_ = &bind_class; 100 | std::vector< Descriptor > descriptors; 101 | descriptors.reserve( static_methodList.size() + methodList.size() ); 102 | add_static_methods( env, static_methodList, descriptors ); 103 | add_methods( env, methodList, descriptors ); 104 | 105 | auto function = 106 | Wrapper::DefineClass( env, name.c_str(), descriptors ); 107 | constructor_ = Napi::Persistent( function ); 108 | constructor_.SuppressDestruct(); 109 | target.Set( name.c_str(), function ); 110 | } 111 | 112 | private: 113 | void add_static_methods( Napi::Env& env, 114 | const std::deque< MethodDefinition >& methodList, 115 | std::vector< Descriptor >& descriptors ) 116 | { 117 | for( const auto& method : methodList ) 118 | { 119 | auto* method_param = new genepi::SignatureParam; 120 | method_param->method_number = method.number(); 121 | descriptors.emplace_back( 122 | Wrapper::StaticMethod( method.name().c_str(), 123 | method.signature()->caller(), napi_default, 124 | static_cast< void* >( 125 | Napi::External< genepi::SignatureParam >::New( 126 | env, method_param ) 127 | .Data() ) ) ); 128 | } 129 | } 130 | 131 | void add_methods( Napi::Env& env, 132 | const std::deque< MethodDefinition >& methodList, 133 | std::vector< Descriptor >& descriptors ) 134 | { 135 | for( const auto& method : methodList ) 136 | { 137 | auto* method_param = new genepi::SignatureParam; 138 | method_param->method_number = method.number(); 139 | method_param->callable = method.signature()->caller(); 140 | method_param->bind_class = bind_class_; 141 | descriptors.emplace_back( Wrapper::InstanceMethod( 142 | method.name().c_str(), &Wrapper::call_method, napi_default, 143 | static_cast< void* >( 144 | Napi::External< genepi::SignatureParam >::New( 145 | env, method_param ) 146 | .Data() ) ) ); 147 | } 148 | } 149 | 150 | Napi::Value call_method( const Napi::CallbackInfo& info ) 151 | { 152 | return SignatureParam::get( info )->callable( info ); 153 | } 154 | 155 | protected: 156 | Napi::FunctionReference constructor_; 157 | std::shared_ptr< Bound > underlying_class_; 158 | BindClassBase* bind_class_{ nullptr }; 159 | }; 160 | 161 | template < class Bound > 162 | class ClassWrapper : public Napi::ObjectWrap< ClassWrapper< Bound > >, 163 | public ClassWrapperBase< Bound > 164 | { 165 | public: 166 | ClassWrapper( const Napi::CallbackInfo& info ); 167 | 168 | struct NoDeleter 169 | { 170 | void operator()( Bound* /* unused */ ) const {} 171 | }; 172 | }; 173 | } // namespace genepi 174 | -------------------------------------------------------------------------------- /include/genepi/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | -------------------------------------------------------------------------------- /include/genepi/creator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | namespace genepi 29 | { 30 | template < class Bound, typename ArgList > 31 | struct Creator; 32 | 33 | template < class Bound, typename... Args > 34 | struct Creator< Bound, TypeList< Args... > > 35 | { 36 | public: 37 | static void create( const Napi::CallbackInfo& args ) 38 | { 39 | ClassWrapper< Bound >::create_obj( 40 | args, Args( args ).get( args )... ); 41 | } 42 | }; 43 | } // namespace genepi 44 | -------------------------------------------------------------------------------- /include/genepi/function_definer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | namespace genepi 30 | { 31 | class FunctionDefiner 32 | { 33 | public: 34 | template < typename ReturnType, typename... Args > 35 | FunctionDefiner( std::string name, 36 | ReturnType ( *function )( Args... ), 37 | std::string bounded_name = std::string{} ) 38 | { 39 | using Signature = FunctionSignature< decltype( function ), 40 | std::nullptr_t, ReturnType, Args... >; 41 | if( bounded_name.empty() ) 42 | { 43 | bounded_name = std::move( name ); 44 | } 45 | register_function( std::move( bounded_name ), 46 | Signature::add_method( function ), &Signature::instance() ); 47 | } 48 | 49 | template < typename ReturnType, typename... Args > 50 | struct Overloaded 51 | { 52 | Overloaded( std::string name, 53 | ReturnType ( *function )( Args... ), 54 | std::string bounded_name ) 55 | { 56 | FunctionDefiner{ std::move( name ), function, 57 | std::move( bounded_name ) }; 58 | } 59 | }; 60 | }; 61 | 62 | } // namespace genepi 63 | -------------------------------------------------------------------------------- /include/genepi/function_definition.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace genepi 31 | { 32 | // Storage format for method definitions. 33 | class FunctionDefinition : public MethodDefinition 34 | { 35 | public: 36 | FunctionDefinition( 37 | std::string name, unsigned int number, BaseSignature* signature ) 38 | : MethodDefinition( std::move( name ), number, signature ) 39 | { 40 | } 41 | 42 | void initialize( Napi::Env& env, Napi::Object& exports ) 43 | { 44 | auto param = new genepi::SignatureParam; 45 | param->method_number = number(); 46 | export_path( name(), 47 | Napi::Function::New( env, signature()->caller(), "", 48 | static_cast< void* >( 49 | Napi::External< genepi::SignatureParam >::New( 50 | env, param ) 51 | .Data() ) ), 52 | exports ); 53 | } 54 | 55 | private: 56 | void export_path( 57 | const std::string& path, Napi::Value value, Napi::Object obj ) 58 | { 59 | auto last_object = obj; 60 | const auto tokens = split( path ); 61 | for( auto i = 0; i != tokens.size() - 1; i++ ) 62 | { 63 | const auto& property = tokens[i]; 64 | Napi::Value prop_value = last_object.Get( property ); 65 | if( prop_value.IsObject() ) 66 | { 67 | last_object = prop_value.As< Napi::Object >(); 68 | } 69 | else if( prop_value.IsUndefined() ) 70 | { 71 | auto new_object = Napi::Object::New( obj.Env() ); 72 | last_object.DefineProperty( Napi::PropertyDescriptor::Value( 73 | property, new_object, napi_default_jsproperty ) ); 74 | last_object = new_object; 75 | } 76 | else 77 | { 78 | throw Napi::Error::New( 79 | obj.Env(), "Attempted to set property \"" + property 80 | + "\" on a non-object" ); 81 | } 82 | } 83 | last_object.DefineProperty( Napi::PropertyDescriptor::Value( 84 | tokens.back(), value, napi_default_jsproperty ) ); 85 | } 86 | 87 | std::vector< std::string > split( const std::string& s ) 88 | { 89 | std::vector< std::string > output; 90 | std::string::size_type prev_pos = 0, pos = 0; 91 | while( ( pos = s.find( "__", pos ) ) != std::string::npos ) 92 | { 93 | std::string substring( s.substr( prev_pos, pos - prev_pos ) ); 94 | output.push_back( substring ); 95 | pos += 2; 96 | prev_pos = pos; 97 | } 98 | output.push_back( 99 | s.substr( prev_pos, pos - prev_pos ) ); // Last word 100 | return output; 101 | } 102 | }; 103 | } // namespace genepi 104 | -------------------------------------------------------------------------------- /include/genepi/genepi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #define GENEPI_CLASS( name ) \ 34 | template < class Bound > \ 35 | struct ClassInvoker##name \ 36 | { \ 37 | ClassInvoker##name(); \ 38 | genepi::ClassDefiner< name > definer; \ 39 | }; \ 40 | static struct ClassInvoker##name< name > classInvoker##name; \ 41 | template < class Bound > \ 42 | ClassInvoker##name< Bound >::ClassInvoker##name() : definer( #name ) 43 | 44 | #define NAMED_GENEPI_CLASS( name, bounded_name ) \ 45 | template < class Bound > \ 46 | struct ClassInvoker##bounded_name \ 47 | { \ 48 | ClassInvoker##bounded_name(); \ 49 | genepi::ClassDefiner< name > definer; \ 50 | }; \ 51 | static struct ClassInvoker##bounded_name< name > \ 52 | bindInvoker##bounded_name; \ 53 | template < class Bound > \ 54 | ClassInvoker##bounded_name< Bound >::ClassInvoker##bounded_name() \ 55 | : definer( #bounded_name ) 56 | 57 | #define GENEPI_CONSTRUCTOR( ... ) definer.add_constructor< __VA_ARGS__ >() 58 | 59 | #define GENEPI_METHOD( name ) definer.add_method( #name, &Bound::name ) 60 | 61 | #define NAMED_GENEPI_METHOD( name, bounded_name ) \ 62 | definer.add_method( #name, &Bound::name, bounded_name ) 63 | 64 | #define GENEPI_MULTIMETHOD( name, return_type, bounded_name, ... ) \ 65 | definer.overloaded< return_type, ##__VA_ARGS__ >().add_method( \ 66 | #name, &Bound::name, bounded_name ) 67 | 68 | #define GENEPI_INHERIT( name ) definer.add_inherit< name >() 69 | 70 | #define GENEPI_FUNCTION( name ) \ 71 | genepi::FunctionDefiner definer##name( #name, &name ) 72 | 73 | #define NAMED_GENEPI_FUNCTION( name, bounded_name ) \ 74 | genepi::FunctionDefiner definer##bounded_name( #name, &name, #bounded_name ) 75 | 76 | #define GENEPI_MULTIFUNCTION( name, return_type, bounded_name, ... ) \ 77 | genepi::FunctionDefiner::template Overloaded< return_type, ##__VA_ARGS__ > \ 78 | definer##bounded_name( #name, &name, #bounded_name ) 79 | 80 | #define GENEPI_MODULE( module_name ) \ 81 | Napi::Object initialize( Napi::Env env, Napi::Object exports ) \ 82 | { \ 83 | for( auto& func : genepi::function_list() ) \ 84 | { \ 85 | func.initialize( env, exports ); \ 86 | } \ 87 | \ 88 | for( auto* cur_class : genepi::class_list() ) \ 89 | { \ 90 | cur_class->initialize( env, exports ); \ 91 | } \ 92 | return exports; \ 93 | } \ 94 | NODE_API_MODULE( module_name, initialize ) 95 | -------------------------------------------------------------------------------- /include/genepi/genepi_registry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | namespace genepi 32 | { 33 | class BindClassBase; 34 | 35 | std::vector< FunctionDefinition > genepi_api& function_list(); 36 | 37 | std::vector< BindClassBase* > genepi_api& class_list(); 38 | 39 | void genepi_api register_function( 40 | std::string name, unsigned int number, BaseSignature* signature ); 41 | 42 | void genepi_api register_class( BindClassBase& bindClass ); 43 | 44 | } // namespace genepi 45 | -------------------------------------------------------------------------------- /include/genepi/method_definition.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | namespace genepi 29 | { 30 | class BaseSignature; 31 | } // namespace genepi 32 | 33 | namespace genepi 34 | { 35 | // Storage format for method definitions. 36 | class MethodDefinition 37 | { 38 | public: 39 | MethodDefinition( 40 | std::string name, unsigned int number, BaseSignature* signature ) 41 | : name_( std::move( name ) ), 42 | number_( number ), 43 | signature_( signature ) 44 | { 45 | } 46 | 47 | const std::string& name() const 48 | { 49 | return name_; 50 | } 51 | 52 | unsigned int number() const 53 | { 54 | return number_; 55 | } 56 | 57 | const BaseSignature* signature() const 58 | { 59 | return signature_; 60 | } 61 | 62 | private: 63 | const std::string name_; 64 | // Index to distinguish between functions with identical signatures. 65 | const unsigned int number_; 66 | // Signature represents return and argument types. 67 | const BaseSignature* signature_; 68 | }; 69 | } // namespace genepi 70 | -------------------------------------------------------------------------------- /include/genepi/signature/base_signature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | namespace genepi 30 | { 31 | // Base class for signatures of all constructors, functions and methods. 32 | // A signature represents a unique set of argument and return types, 33 | // and the invoker functions needed to deal with such types. 34 | class BaseSignature 35 | { 36 | public: 37 | BaseSignature( Callable caller, unsigned int arity ) 38 | : caller_( caller ), arity_( arity ) 39 | { 40 | } 41 | 42 | Callable caller() const 43 | { 44 | return caller_; 45 | } 46 | 47 | unsigned int arity() const 48 | { 49 | return arity_; 50 | } 51 | 52 | private: 53 | const Callable caller_; 54 | const unsigned int arity_; 55 | }; 56 | } // namespace genepi 57 | -------------------------------------------------------------------------------- /include/genepi/signature/constructor_signature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace genepi 32 | { 33 | // Constructor. Call() creates an instance of a bound C++ class 34 | template < class Bound, typename... Args > 35 | class ConstructorSignature 36 | : public TemplatedBaseSignature< ConstructorSignature< Bound, Args... >, 37 | Bound *, 38 | Args... > 39 | { 40 | public: 41 | using MethodType = void *; 42 | using ConstructWrapper = Creator< Bound, 43 | typename MapWithIndex< TypeList, ArgFromNapiValue, Args... >:: 44 | type >; 45 | using Parent = 46 | TemplatedBaseSignature< ConstructorSignature, Bound *, Args... >; 47 | 48 | static Napi::Value call( const Napi::CallbackInfo &args ) 49 | { 50 | if( !Parent::CheckWrapper::are_types_valid( args ) ) 51 | { 52 | throw Napi::Error::New( 53 | args.Env(), Parent::CheckWrapper::getTypeError( args ) ); 54 | } 55 | ConstructWrapper::create( args ); 56 | return args.Env().Undefined(); 57 | } 58 | }; 59 | } // namespace genepi 60 | -------------------------------------------------------------------------------- /include/genepi/signature/function_signature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace genepi 31 | { 32 | template < typename PtrType, 33 | class Bound, 34 | typename ReturnType, 35 | typename... Args > 36 | class FunctionSignature 37 | : public TemplatedBaseSignature< 38 | FunctionSignature< PtrType, Bound, ReturnType, Args... >, 39 | ReturnType, 40 | Args... > 41 | { 42 | public: 43 | using MethodType = PtrType; 44 | using Parent = 45 | TemplatedBaseSignature< FunctionSignature, ReturnType, Args... >; 46 | 47 | static Napi::Value call_inner( 48 | const typename Parent::MethodInfo &method, 49 | const Napi::CallbackInfo &args, 50 | void * ) 51 | { 52 | return Parent::CallWrapper::call_function( method.func, args ); 53 | } 54 | 55 | static Napi::Value call( const Napi::CallbackInfo &args ) 56 | { 57 | return Parent::template call_inner_safely< void >( 58 | args, SignatureParam::get( args )->method_number ); 59 | } 60 | }; 61 | } // namespace genepi 62 | -------------------------------------------------------------------------------- /include/genepi/signature/method_signature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace genepi 31 | { 32 | template < typename PtrType, 33 | class Bound, 34 | typename ReturnType, 35 | typename... Args > 36 | class MethodSignature 37 | : public TemplatedBaseSignature< 38 | MethodSignature< PtrType, Bound, ReturnType, Args... >, 39 | ReturnType, 40 | Args... > 41 | { 42 | public: 43 | using MethodType = PtrType; 44 | using Parent = 45 | TemplatedBaseSignature< MethodSignature, ReturnType, Args... >; 46 | 47 | static Napi::Value call_inner( 48 | const typename Parent::MethodInfo &method, 49 | const Napi::CallbackInfo &args, 50 | Bound *target ) 51 | { 52 | return Parent::CallWrapper::call_method( 53 | *target, method.func, args ); 54 | } 55 | 56 | static Napi::Value call( const Napi::CallbackInfo &args ) 57 | { 58 | return Parent::template call_inner_safely< Bound >( 59 | args, SignatureParam::get( args )->method_number ); 60 | } 61 | }; 62 | 63 | } // namespace genepi 64 | -------------------------------------------------------------------------------- /include/genepi/signature/signature_param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | #include 29 | 30 | namespace genepi 31 | { 32 | class BindClassBase; 33 | } // namespace genepi 34 | 35 | namespace genepi 36 | { 37 | struct SignatureParam 38 | { 39 | static SignatureParam* get( const Napi::CallbackInfo& info ) 40 | { 41 | return static_cast< genepi::SignatureParam* >( info.Data() ); 42 | } 43 | 44 | // Distinguish methods with identical signatures. 45 | unsigned int method_number = 0; 46 | 47 | Callable callable; 48 | 49 | BindClassBase* bind_class{ nullptr }; 50 | }; 51 | } // namespace genepi 52 | -------------------------------------------------------------------------------- /include/genepi/signature/templated_base_signature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace genepi 36 | { 37 | // Templated static class for each different function call signature exposed 38 | // by the Node.js plugin. Used to pass arguments and return values between 39 | // C++ and Node.js. Everything must be static because the V8 JavaScript 40 | // engine wants a single function pointer to call, so each template variant 41 | // is a singleton class. 42 | template < class Signature, typename ReturnType, typename... Args > 43 | class TemplatedBaseSignature : public BaseSignature 44 | { 45 | public: 46 | TemplatedBaseSignature() 47 | : BaseSignature( Signature::call, sizeof...( Args ) ) 48 | { 49 | } 50 | 51 | static Signature& instance() 52 | { 53 | static Signature instance; 54 | return instance; 55 | } 56 | 57 | // Information about a single named function. 58 | // This wrapper around Signature::MethodType is needed because 59 | // TemplatedBaseSignature itself cannot see the type directly. It's 60 | // passed as a CRTP argument and is not fully defined here, but inside 61 | // an inner class that doesn't matter. 62 | struct MethodInfo 63 | { 64 | using MethodType = typename Signature::MethodType; 65 | 66 | MethodInfo( MethodType func ) : func( func ) {} 67 | 68 | const MethodType func; 69 | }; 70 | 71 | static const MethodInfo& method( unsigned int number ) 72 | { 73 | return instance().functions_[number]; 74 | } 75 | 76 | template < typename MethodType > 77 | static unsigned int add_method( MethodType func ) 78 | { 79 | auto& functions = instance().functions_; 80 | functions.emplace_back( func ); 81 | return static_cast< unsigned int >( functions.size() - 1 ); 82 | } 83 | 84 | using CallWrapper = Caller< ReturnType, 85 | typename MapWithIndex< TypeList, ArgFromNapiValue, Args... >:: 86 | type >; 87 | 88 | using CheckWrapper = Checker< 89 | typename MapWithIndex< TypeList, CheckNapiValue, Args... >::type >; 90 | 91 | template < typename Bound > 92 | static Bound* get_target_safely( 93 | const Napi::CallbackInfo& info, Bound* target ) 94 | { 95 | return ClassWrapper< Bound >::get_bound( info ); 96 | } 97 | 98 | static void* get_target_safely( 99 | const Napi::CallbackInfo& info, void* target ) 100 | { 101 | return nullptr; 102 | } 103 | 104 | template < typename Bound > 105 | static Napi::Value call_inner_safely( 106 | const Napi::CallbackInfo& info, unsigned int method_number ) 107 | { 108 | Bound* target = nullptr; 109 | if( info.Length() != sizeof...( Args ) ) 110 | { 111 | // TODO: When function is overloaded, this test could be 112 | // skipped... 113 | throw Napi::Error::New( 114 | info.Env(), "Wrong number of arguments, expected " 115 | + std::to_string( sizeof...( Args ) ) ); 116 | } 117 | 118 | if( !CheckWrapper::are_types_valid( info ) ) 119 | { 120 | throw Napi::Error::New( 121 | info.Env(), CheckWrapper::getTypeError( info ) ); 122 | } 123 | 124 | try 125 | { 126 | target = get_target_safely( info, target ); 127 | return Signature::call_inner( 128 | method( method_number ), info, target ); 129 | } 130 | catch( const std::exception& ex ) 131 | { 132 | throw Napi::Error::New( info.Env(), ex.what() ); 133 | } 134 | } 135 | 136 | private: 137 | // The functions_ vector cannot be moved to BaseSignature because it can 138 | // contain pointers to functions or class methods, and there isn't a 139 | // single pointer type able to hold both. 140 | std::vector< MethodInfo > functions_; 141 | }; 142 | } // namespace genepi 143 | -------------------------------------------------------------------------------- /include/genepi/singleton.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | namespace genepi 32 | { 33 | /*! 34 | * Cross platform singleton implementation 35 | * Classic templated singleton cannot be exported on Windows. 36 | * To ensure a unique instance of the singleton, we store it and 37 | * export methods to retrieve the unique instance. 38 | * 39 | * To use this class, inherit from it and use the protected 40 | * method Singleton::instance(). 41 | */ 42 | class genepi_api Singleton 43 | { 44 | public: 45 | virtual ~Singleton(); 46 | 47 | protected: 48 | Singleton(); 49 | 50 | template < class SingletonType > 51 | static SingletonType &instance() 52 | { 53 | auto singleton = dynamic_cast< SingletonType * >( 54 | instance( typeid( SingletonType ) ) ); 55 | if( singleton == nullptr ) 56 | { 57 | singleton = new SingletonType{}; 58 | set_instance( typeid( SingletonType ), singleton ); 59 | } 60 | 61 | return *singleton; 62 | } 63 | 64 | private: 65 | static Singleton &instance(); 66 | static void set_instance( 67 | const std::type_info &type, Singleton *singleton ); 68 | static Singleton *instance( const std::type_info &type ); 69 | 70 | private: 71 | class Impl; 72 | std::unique_ptr< Impl > impl_; 73 | }; 74 | } // namespace genepi 75 | -------------------------------------------------------------------------------- /include/genepi/type_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | namespace genepi 27 | { 28 | // TypeList<> 29 | 30 | template < typename... > 31 | struct TypeList 32 | { 33 | }; 34 | 35 | // Cons :: T, TypeList -> Cons 36 | template < typename First, typename TypeList > 37 | struct Cons; 38 | 39 | template < typename First, typename... Rest > 40 | struct Cons< First, TypeList< Rest... > > 41 | { 42 | using type = TypeList< First, Rest... >; 43 | }; 44 | 45 | // Apply :: T, TypeList -> T 46 | template < template < typename... > class Output, typename TypeList > 47 | struct Apply; 48 | 49 | template < template < typename... > class Output, typename... Types > 50 | struct Apply< Output, TypeList< Types... > > 51 | { 52 | using type = Output< Types... >; 53 | }; 54 | 55 | // MapWithIndex_ 56 | template < template < size_t, typename > class Mapper, 57 | size_t CurrentIndex, 58 | typename... Args > 59 | struct MapWithIndex_; 60 | 61 | template < template < size_t, typename > class Mapper, 62 | size_t CurrentIndex, 63 | typename First, 64 | typename... Rest > 65 | struct MapWithIndex_< Mapper, CurrentIndex, First, Rest... > 66 | { 67 | using type = typename Cons< Mapper< CurrentIndex, First >, 68 | typename MapWithIndex_< Mapper, CurrentIndex + 1, Rest... >:: 69 | type >::type; 70 | }; 71 | 72 | template < template < size_t, typename > class Mapper, size_t CurrentIndex > 73 | struct MapWithIndex_< Mapper, CurrentIndex > 74 | { 75 | using type = TypeList<>; 76 | }; 77 | 78 | template < template < typename... > class Output, 79 | template < size_t, typename > 80 | class Mapper, 81 | typename... Args > 82 | struct MapWithIndex 83 | { 84 | using type = typename Apply< Output, 85 | typename MapWithIndex_< Mapper, 0, Args... >::type >::type; 86 | }; 87 | } // namespace genepi 88 | -------------------------------------------------------------------------------- /include/genepi/type_transformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | #include 29 | 30 | namespace genepi 31 | { 32 | template < typename ArgType > 33 | struct TypeTransformer 34 | { 35 | using Binding = BindingType< ArgType >; 36 | using Type = typename Binding::Type; 37 | }; 38 | 39 | template < typename ArgType > 40 | typename TypeTransformer< ArgType >::Type convertFromNapiValue( 41 | Napi::Value arg ) 42 | { 43 | return TypeTransformer< ArgType >::Binding::fromNapiValue( arg ); 44 | } 45 | 46 | // Convert any C++ type to the corresponding JavaScript type. 47 | // Call correct type converter using perfect forwarding (moving doesn't 48 | // work). 49 | template < typename ReturnType > 50 | Napi::Value convertToNapiValue( Napi::Env env, ReturnType result ) 51 | { 52 | return TypeTransformer< ReturnType >::Binding::toNapiValue( 53 | env, std::forward< ReturnType >( result ) ); 54 | } 55 | } // namespace genepi 56 | -------------------------------------------------------------------------------- /include/genepi/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | 28 | namespace genepi 29 | { 30 | using Callable = 31 | std::add_pointer< Napi::Value( const Napi::CallbackInfo& ) >::type; 32 | 33 | template < typename ArgType > 34 | struct BindingType; 35 | } // namespace genepi 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@geode/genepi", 3 | "license": "MIT", 4 | "version": "0.0.0-semantically-released", 5 | "description": "Automatic generation of N-API wrapper from a C++ library", 6 | "author": "Geode-solutions", 7 | "keywords": [ 8 | "n-api", 9 | "napi", 10 | "wrapper", 11 | "c++", 12 | "addon", 13 | "module", 14 | "bindings", 15 | "cmake" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/Geode-solutions/genepi.git" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/Geode-solutions/genepi/issues" 23 | }, 24 | "homepage": "https://github.com/Geode-solutions/genepi#readme", 25 | "scripts": { 26 | "build": "cmake-js compile", 27 | "build:debug": "cmake-js compile -D", 28 | "install": "cmake-js compile", 29 | "examples": "node ./examples/index.js" 30 | }, 31 | "files": [ 32 | "/cmake", 33 | "/include", 34 | "/src", 35 | "/CMakeLists.txt" 36 | ], 37 | "publishConfig": { 38 | "access": "public" 39 | }, 40 | "dependencies": { 41 | "cmake-js": "^6.1.0", 42 | "node-addon-api": "^1.7.2" 43 | }, 44 | "devDependencies": { 45 | "bindings": "^1.5.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/genepi/common.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | 26 | namespace genepi 27 | { 28 | std::vector< FunctionDefinition >& function_list() 29 | { 30 | static std::vector< FunctionDefinition > functionList; 31 | return functionList; 32 | } 33 | 34 | std::vector< BindClassBase* >& class_list() 35 | { 36 | static std::vector< BindClassBase* > classList; 37 | return classList; 38 | } 39 | 40 | void register_function( 41 | std::string name, unsigned int number, BaseSignature* signature ) 42 | { 43 | function_list().emplace_back( std::move( name ), number, signature ); 44 | } 45 | 46 | void register_class( BindClassBase& bindClass ) 47 | { 48 | class_list().emplace_back( &bindClass ); 49 | } 50 | } // namespace genepi 51 | -------------------------------------------------------------------------------- /src/genepi/genepi_registry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | 26 | namespace genepi 27 | { 28 | std::vector< FunctionDefinition >& function_list() 29 | { 30 | static std::vector< FunctionDefinition > functionList; 31 | return functionList; 32 | } 33 | 34 | std::vector< BindClassBase* >& class_list() 35 | { 36 | static std::vector< BindClassBase* > classList; 37 | return classList; 38 | } 39 | 40 | void register_function( 41 | std::string name, unsigned int number, BaseSignature* signature ) 42 | { 43 | function_list().emplace_back( std::move( name ), number, signature ); 44 | } 45 | 46 | void register_class( BindClassBase& bindClass ) 47 | { 48 | class_list().emplace_back( &bindClass ); 49 | } 50 | } // namespace genepi 51 | -------------------------------------------------------------------------------- /src/genepi/singleton.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 - 2021 Geode-solutions 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | * 22 | */ 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | namespace genepi 30 | { 31 | class Singleton::Impl 32 | { 33 | public: 34 | void set_instance( const std::type_info &type, Singleton *singleton ) 35 | { 36 | singletons_[type.name()].reset( singleton ); 37 | } 38 | 39 | Singleton *instance( const std::type_info &type ) 40 | { 41 | auto iter = singletons_.find( type.name() ); 42 | if( iter == singletons_.end() ) 43 | { 44 | return nullptr; 45 | } 46 | return iter->second.get(); 47 | } 48 | 49 | private: 50 | std::map< std::string, std::unique_ptr< Singleton > > singletons_; 51 | }; 52 | 53 | Singleton::Singleton() : impl_( new Impl ) {} 54 | 55 | Singleton::~Singleton() {} 56 | 57 | Singleton &Singleton::instance() 58 | { 59 | static Singleton singleton; 60 | return singleton; 61 | } 62 | 63 | void Singleton::set_instance( 64 | const std::type_info &type, Singleton *singleton ) 65 | { 66 | instance().impl_->set_instance( type, singleton ); 67 | } 68 | 69 | Singleton *Singleton::instance( const std::type_info &type ) 70 | { 71 | return instance().impl_->instance( type ); 72 | } 73 | } // namespace genepi 74 | --------------------------------------------------------------------------------