├── README.md ├── cmakelists.txt ├── doc ├── build │ ├── Doxyfile │ ├── Doxygen.hpp │ ├── doxygen.css │ ├── footer.htm │ └── header.htm └── html │ └── logo.png ├── example ├── PlumaCoreTest │ ├── cmakelists.txt │ └── main.cpp ├── cmakelists.txt ├── src │ ├── host │ │ └── main.cpp │ ├── interface │ │ └── Warrior.hpp │ └── plugin │ │ ├── Eagle.cpp │ │ ├── Eagle.hpp │ │ ├── Jaguar.cpp │ │ ├── Jaguar.hpp │ │ ├── SimpleWarrior.cpp │ │ └── SimpleWarrior.hpp ├── testPlumaCore │ └── main.cpp └── testPlumaPlugins │ ├── interface │ └── Warrior.hpp │ ├── loaderManager │ └── main.cpp │ └── plugin │ ├── Eagle.cpp │ ├── Eagle.hpp │ ├── Jaguar.cpp │ ├── Jaguar.hpp │ ├── SimpleWarrior.cpp │ └── SimpleWarrior.hpp ├── include └── Pluma │ ├── Config.hpp │ ├── Connector.hpp │ ├── Host.hpp │ ├── PluginManager.hpp │ ├── Pluma.hpp │ ├── Pluma.inl │ ├── PlumaCore.hpp │ ├── PlumaPipe.hpp │ └── Provider.hpp └── src └── Pluma ├── DLibrary.cpp ├── DLibrary.hpp ├── Dir.cpp ├── Dir.hpp ├── Host.cpp ├── PluginManager.cpp ├── PlumaCore.cpp ├── PlumaCore.h ├── PlumaPipe.cpp ├── PlumaPipe.h ├── Provider.cpp ├── cmakelists.txt ├── out └── build │ └── x64-Debug (默认值) │ └── VSInheritEnvironments.txt └── uce-dirent.h /README.md: -------------------------------------------------------------------------------- 1 | Pluma - Plug-in Management Framework 2 | 3 | 1. About 4 | 5 | Pluma stands for PLUg-in MAnagement framework, and also for PLUg-in Minimal Architecture. 6 | It's small, cross-platform and simple to use. Support and more information at http://pluma-framework.sourceforge.net 7 | 8 | 9 | 2. Licence 10 | 11 | Source code is provided under the terms of the zlib/libpng License (http://www.opensource.org/licenses/zlib-license.php): 12 | 13 | Pluma - Plug-in Management Framework 14 | Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 15 | 16 | This software is provided 'as-is', without any express or implied warranty. 17 | In no event will the authors be held liable for any damages arising from the use of this software. 18 | 19 | Permission is granted to anyone to use this software for any purpose, 20 | including commercial applications, and to alter it and redistribute it freely, 21 | subject to the following restrictions: 22 | 23 | 1. The origin of this software must not be misrepresented; 24 | you must not claim that you wrote the original software. 25 | If you use this software in a product, an acknowledgment 26 | in the product documentation would be appreciated but is not required. 27 | 28 | 2. Altered source versions must be plainly marked as such, 29 | and must not be misrepresented as being the original software. 30 | 31 | 3. This notice may not be removed or altered from any source distribution. 32 | 33 | 34 | 3. First of all, thank the original author for his hard work, and then thank the GNU program. 35 | Since the official author has not updated this framework for many years, nor has it adapted to cmake, 36 | the source code has been tested and the structure has been changed here. 37 | 2020-06-06 FunNing 38 | 39 | 首先感谢原作者的辛勤劳作,再者感谢GNU计划。 40 | 由于官方作者多年未更新此框架,也并未适配cmake, 41 | 这里针对源码进行了测试和结构进行改动。 42 | 2020-06-06 FunNing 43 | 44 | -------------------------------------------------------------------------------- /cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.0) 2 | 3 | project(Pluma) 4 | 5 | set(CMAKE_BUILD_RPATH ${CMAKE_CURRENT_SOURCE_DIR}/build) 6 | message(${CMAKE_BUILD_RPATH}) 7 | 8 | add_definitions( 9 | -DPLUMA_EXPORTS 10 | ) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BUILD_RPATH}/lib_Debug) 13 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BUILD_RPATH}/lib_Release) 14 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BUILD_RPATH}/lib_MinSizeRel) 15 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BUILD_RPATH}/lib_RelInfoDebug) 16 | 17 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BUILD_RPATH}/bin_Debug) 18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BUILD_RPATH}/bin_Release) 19 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BUILD_RPATH}/bin_MinSizeRel) 20 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BUILD_RPATH}/bin_RelInfoDebug) 21 | 22 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BUILD_RPATH}/lib_Debug) 23 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BUILD_RPATH}/lib_Release) 24 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BUILD_RPATH}/lib_MinSizeRel) 25 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BUILD_RPATH}/lib_RelInfoDebug) 26 | 27 | set(SOURCE_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include) 28 | set(SOURCE_CPP ${CMAKE_CURRENT_SOURCE_DIR}/src) 29 | 30 | include_directories( 31 | ${SOURCE_HEAD} 32 | ${SOURCE_HEAD}/Pluma 33 | ${SOURCE_CPP} 34 | ${SOURCE_CPP}/Pluma 35 | ) 36 | 37 | aux_source_directory(${SOURCE_CPP}/Pluma PlumaStaticSRC) 38 | 39 | add_library(Pluma STATIC ${PlumaStaticSRC}) 40 | 41 | subdirs(${CMAKE_CURRENT_SOURCE_DIR}/example) 42 | -------------------------------------------------------------------------------- /doc/build/Doxygen.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | /// \mainpage 3 | /// 4 | /// \section welcome Welcome 5 | /// Welcome to Pluma documentation. Here you will find a detailed 6 | /// view of all Pluma classes.
7 | /// If you are looking for support, you can visit the official website 8 | /// at http://pluma-framework.sourceforge.net/.

9 | /// 10 | /// CSS based on SFML1.6 documentation
11 | /// 12 | /// \section example Short Example 13 | /// A short example to demonstrate Pluma usage:
14 | /// A host application define a Device interface. A certain plugin 15 | /// defines a Keyboard, witch is a Device. 16 | /// The host will use DeviceProviders to create objects of type Device. 17 | /// The plugin will provide host specifically with a KeyboardProvider.
18 | /// 19 | /// Device hpp (shared): 20 | /// \code 21 | /// #include 22 | /// class Device{ 23 | /// public: 24 | /// virtual std::string getDescription() const = 0; 25 | /// }; 26 | /// // create DevicedProvider class 27 | /// PLUMA_PROVIDER_HEADER(Device); 28 | /// \endcode 29 | /// 30 | /// Device cpp (shared): 31 | /// \code 32 | /// #include "Device.hpp" 33 | /// generate DevicedProvider with version 6, and compatible with at least v.3 34 | /// PLUMA_PROVIDER_SOURCE(Device, 6, 3); 35 | /// \endcode 36 | /// 37 | /// 38 | ///
39 | /// Keyboard code on the plugin side: 40 | /// \code 41 | /// #include 42 | /// #include "Device.hpp" 43 | /// 44 | /// class Keyboard: public Device{ 45 | /// public: 46 | /// std::string getDescription() const{ 47 | /// return "keyboard"; 48 | /// } 49 | /// }; 50 | /// 51 | /// // create KeyboardProvider, it implements DeviceProvider 52 | /// PLUMA_INHERIT_PROVIDER(Keyboard, Device); 53 | /// \endcode 54 | /// 55 | /// plugin connector: 56 | /// \code 57 | /// #include 58 | /// #include "Keyboard.hpp" 59 | /// 60 | /// PLUMA_CONNECTOR 61 | /// bool connect(pluma::Host& host){ 62 | /// // add a keyboard provider to host 63 | /// host.add( new KeyboardProvider() ); 64 | /// return true; 65 | /// } 66 | /// \endcode 67 | /// 68 | /// 69 | /// Host application code: 70 | /// \code 71 | /// #include 72 | /// 73 | /// #include "Device.hpp" 74 | /// #include 75 | /// #include 76 | /// 77 | /// int main(){ 78 | /// 79 | /// pluma::Pluma plugins; 80 | /// // Tell plugins manager to accept providers of the type DeviceProvider 81 | /// plugins.acceptProviderType(); 82 | /// // Load library "standard_devices" from folder "plugins" 83 | /// plugins.load("plugins", "standard_devices"); 84 | /// 85 | /// // Get device providers into a vector 86 | /// std::vector providers; 87 | /// plugins.getProviders(providers); 88 | /// 89 | /// // create a Device from the first provider 90 | /// if (!providers.empty()){ 91 | /// Device* myDevice = providers.first()->create(); 92 | /// // do something with myDevice 93 | /// std::cout << device->getDescription() << std::endl; 94 | /// // and delete it in the end 95 | /// delete myDevice; 96 | /// } 97 | /// return 0; 98 | /// } 99 | /// \endcode 100 | /// 101 | //////////////////////////////////////////////////////////// 102 | -------------------------------------------------------------------------------- /doc/build/doxygen.css: -------------------------------------------------------------------------------- 1 | div#logo 2 | { 3 | margin-bottom : 1em; 4 | background : url("./logo-bg.jpg") repeat-x; 5 | } 6 | 7 | div#logo a 8 | { 9 | display : block; 10 | } 11 | 12 | p#footer 13 | { 14 | text-decoration : overline; 15 | color : #606060; 16 | padding-top : 1em; 17 | text-align : center; 18 | font-size : smaller; 19 | } 20 | 21 | p#footer a 22 | { 23 | color : #007298; 24 | text-decoration : none; 25 | } 26 | 27 | BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { 28 | font-family: Geneva, Arial, Helvetica, sans-serif; 29 | } 30 | BODY,TD { 31 | font-size: 90%; 32 | } 33 | H1 { 34 | text-align : center; 35 | margin-top : 0px; 36 | color : #2090B0; 37 | font-size : 160%; 38 | } 39 | H2 { 40 | font-size: 120%; 41 | } 42 | H3 { 43 | font-size: 100%; 44 | } 45 | CAPTION { font-weight: bold } 46 | DIV.qindex { 47 | width: 100%; 48 | background-color: #E0FFE0; 49 | border: 1px dotted #808080; 50 | text-align: center; 51 | margin: 2px; 52 | padding: 2px; 53 | line-height: 140%; 54 | } 55 | DIV.nav { 56 | width: 100%; 57 | background-color: #e8eef2; 58 | border: 1px solid #84b0c7; 59 | text-align: center; 60 | margin: 2px; 61 | padding: 2px; 62 | line-height: 140%; 63 | } 64 | DIV.navtab { 65 | background-color: #e8eef2; 66 | border: 1px solid #84b0c7; 67 | text-align: center; 68 | margin: 2px; 69 | margin-right: 15px; 70 | padding: 2px; 71 | } 72 | TD.navtab { 73 | font-size: 70%; 74 | } 75 | A.qindex { 76 | text-decoration: none; 77 | font-weight: bold; 78 | } 79 | A.qindex:visited { 80 | text-decoration: none; 81 | font-weight: bold; 82 | } 83 | A.qindex:hover { 84 | text-decoration: none; 85 | background-color: #ddddff; 86 | } 87 | A.qindexHL { 88 | text-decoration: none; 89 | font-weight: bold; 90 | background-color: #6666cc; 91 | color: #ffffff; 92 | border: 1px double #9295C2; 93 | } 94 | A.qindexHL:hover { 95 | text-decoration: none; 96 | background-color: #6666cc; 97 | color: #ffffff; 98 | } 99 | A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } 100 | A.el { text-decoration: none; font-weight: bold } 101 | A.elRef { font-weight: bold } 102 | A.code:link { text-decoration: none; font-weight: normal; border-bottom : 1px dotted #808080; color: black;} 103 | A.code:visited { text-decoration: none; font-weight: normal; border-bottom : 1px dotted #808080; color: black;} 104 | A.codeRef:link { font-weight: normal; color: #0000FF} 105 | A.codeRef:visited { font-weight: normal; color: #0000FF} 106 | /*A:hover { text-decoration: none; background-color: #f2f2ff }*/ 107 | DL.el { margin-left: -1cm } 108 | .fragment { 109 | font-family: monospace, fixed; 110 | font-size: 95%; 111 | } 112 | PRE.fragment { 113 | border: 1px solid #CCCCCC; 114 | background-color: #f5f5f5; 115 | margin-top: 4px; 116 | margin-bottom: 4px; 117 | margin-left: 2px; 118 | margin-right: 8px; 119 | padding-left: 6px; 120 | padding-right: 6px; 121 | padding-top: 4px; 122 | padding-bottom: 4px; 123 | } 124 | DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } 125 | 126 | DIV.groupHeader { 127 | margin-left: 16px; 128 | margin-top: 12px; 129 | margin-bottom: 6px; 130 | font-weight: bold; 131 | } 132 | DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } 133 | BODY { 134 | background: white; 135 | color: black; 136 | margin-right: 20px; 137 | margin-left: 20px; 138 | } 139 | TD.indexkey { 140 | background-color: #e8eef2; 141 | font-weight: bold; 142 | padding-right : 10px; 143 | padding-top : 2px; 144 | padding-left : 10px; 145 | padding-bottom : 2px; 146 | margin-left : 0px; 147 | margin-right : 0px; 148 | margin-top : 2px; 149 | margin-bottom : 2px; 150 | border: 1px solid #CCCCCC; 151 | } 152 | TD.indexvalue { 153 | background-color: #e8eef2; 154 | font-style: italic; 155 | padding-right : 10px; 156 | padding-top : 2px; 157 | padding-left : 10px; 158 | padding-bottom : 2px; 159 | margin-left : 0px; 160 | margin-right : 0px; 161 | margin-top : 2px; 162 | margin-bottom : 2px; 163 | border: 1px solid #CCCCCC; 164 | } 165 | TR.memlist { 166 | background-color: #f0f0f0; 167 | } 168 | P.formulaDsp { text-align: center; } 169 | IMG.formulaDsp { } 170 | IMG.formulaInl { vertical-align: middle; } 171 | SPAN.keyword { color: #0000FF } 172 | SPAN.keywordtype { color: #0000FF } 173 | SPAN.keywordflow { color: #0000FF } 174 | SPAN.comment { color: #008000 } 175 | SPAN.preprocessor { color: #008080 } 176 | SPAN.stringliteral { color: #008080 } 177 | SPAN.charliteral { color: #008080 } 178 | .mdescLeft { 179 | padding: 0px 8px 4px 8px; 180 | font-size: 80%; 181 | font-style: italic; 182 | background-color: #FAFAFA; 183 | border-top: 1px none #E0E0E0; 184 | border-right: 1px none #E0E0E0; 185 | border-bottom: 1px none #E0E0E0; 186 | border-left: 1px none #E0E0E0; 187 | margin: 0px; 188 | } 189 | .mdescRight { 190 | padding: 0px 8px 4px 8px; 191 | font-size: 80%; 192 | font-style: italic; 193 | background-color: #FAFAFA; 194 | border-top: 1px none #E0E0E0; 195 | border-right: 1px none #E0E0E0; 196 | border-bottom: 1px none #E0E0E0; 197 | border-left: 1px none #E0E0E0; 198 | margin: 0px; 199 | } 200 | .memItemLeft { 201 | padding: 1px 0px 0px 8px; 202 | margin: 4px; 203 | border-top-width: 1px; 204 | border-right-width: 1px; 205 | border-bottom-width: 1px; 206 | border-left-width: 1px; 207 | border-top-color: #E0E0E0; 208 | border-right-color: #E0E0E0; 209 | border-bottom-color: #E0E0E0; 210 | border-left-color: #E0E0E0; 211 | border-top-style: solid; 212 | border-right-style: none; 213 | border-bottom-style: none; 214 | border-left-style: none; 215 | background-color: #FAFAFA; 216 | font-size: 80%; 217 | } 218 | .memItemRight { 219 | padding: 1px 8px 0px 8px; 220 | margin: 4px; 221 | border-top-width: 1px; 222 | border-right-width: 1px; 223 | border-bottom-width: 1px; 224 | border-left-width: 1px; 225 | border-top-color: #E0E0E0; 226 | border-right-color: #E0E0E0; 227 | border-bottom-color: #E0E0E0; 228 | border-left-color: #E0E0E0; 229 | border-top-style: solid; 230 | border-right-style: none; 231 | border-bottom-style: none; 232 | border-left-style: none; 233 | background-color: #FAFAFA; 234 | font-size: 80%; 235 | } 236 | .memTemplItemLeft { 237 | padding: 1px 0px 0px 8px; 238 | margin: 4px; 239 | border-top-width: 1px; 240 | border-right-width: 1px; 241 | border-bottom-width: 1px; 242 | border-left-width: 1px; 243 | border-top-color: #E0E0E0; 244 | border-right-color: #E0E0E0; 245 | border-bottom-color: #E0E0E0; 246 | border-left-color: #E0E0E0; 247 | border-top-style: none; 248 | border-right-style: none; 249 | border-bottom-style: none; 250 | border-left-style: none; 251 | background-color: #FAFAFA; 252 | font-size: 80%; 253 | } 254 | .memTemplItemRight { 255 | padding: 1px 8px 0px 8px; 256 | margin: 4px; 257 | border-top-width: 1px; 258 | border-right-width: 1px; 259 | border-bottom-width: 1px; 260 | border-left-width: 1px; 261 | border-top-color: #E0E0E0; 262 | border-right-color: #E0E0E0; 263 | border-bottom-color: #E0E0E0; 264 | border-left-color: #E0E0E0; 265 | border-top-style: none; 266 | border-right-style: none; 267 | border-bottom-style: none; 268 | border-left-style: none; 269 | background-color: #FAFAFA; 270 | font-size: 80%; 271 | } 272 | .memTemplParams { 273 | padding: 1px 0px 0px 8px; 274 | margin: 4px; 275 | border-top-width: 1px; 276 | border-right-width: 1px; 277 | border-bottom-width: 1px; 278 | border-left-width: 1px; 279 | border-top-color: #E0E0E0; 280 | border-right-color: #E0E0E0; 281 | border-bottom-color: #E0E0E0; 282 | border-left-color: #E0E0E0; 283 | border-top-style: solid; 284 | border-right-style: none; 285 | border-bottom-style: none; 286 | border-left-style: none; 287 | color: #606060; 288 | background-color: #FAFAFA; 289 | font-size: 80%; 290 | } 291 | .search { color: #003399; 292 | font-weight: bold; 293 | } 294 | FORM.search { 295 | margin-bottom: 0px; 296 | margin-top: 0px; 297 | } 298 | INPUT.search { font-size: 75%; 299 | color: #000080; 300 | font-weight: normal; 301 | background-color: #e8eef2; 302 | } 303 | TD.tiny { font-size: 75%; 304 | } 305 | a { 306 | color: #2090B0; 307 | } 308 | a:visited { 309 | color: #2090B0; 310 | } 311 | .dirtab { padding: 4px; 312 | border-collapse: collapse; 313 | border: 1px solid #84b0c7; 314 | } 315 | TH.dirtab { background: #e8eef2; 316 | font-weight: bold; 317 | } 318 | HR { height: 1px; 319 | border: none; 320 | border-top: 1px solid black; 321 | } 322 | 323 | /* Style for detailed member documentation */ 324 | .memtemplate { 325 | font-size: 80%; 326 | color: #606060; 327 | font-weight: normal; 328 | } 329 | .memnav { 330 | background-color: #e8eef2; 331 | border: 1px solid #84b0c7; 332 | text-align: center; 333 | margin: 2px; 334 | margin-right: 15px; 335 | padding: 2px; 336 | } 337 | .memitem { 338 | /*padding: 4px;*/ 339 | background-color: #F0FFF0; 340 | border-width: 1px; 341 | border-style: solid; 342 | border-color: #808080; 343 | /*-moz-border-radius: 8px 8px 8px 8px;*/ 344 | } 345 | .memname { 346 | white-space: nowrap; 347 | font-weight: bold; 348 | } 349 | .memdoc{ 350 | padding-left: 10px; 351 | } 352 | .memproto { 353 | background-color: #D0FFD0; 354 | width: 100%; 355 | border-bottom-width: 1px; 356 | border-bottom-style: dotted; 357 | border-bottom-color: #808080; 358 | font-weight: bold; 359 | /*-moz-border-radius: 8px 8px 8px 8px;*/ 360 | } 361 | .paramkey { 362 | text-align: right; 363 | } 364 | .paramtype { 365 | white-space: nowrap; 366 | } 367 | .paramname { 368 | color: #602020; 369 | font-style: italic; 370 | white-space: nowrap; 371 | } 372 | /* End Styling for detailed member documentation */ 373 | 374 | /* for the tree view */ 375 | .ftvtree { 376 | font-family: sans-serif; 377 | margin:0.5em; 378 | } 379 | .directory { font-size: 9pt; font-weight: bold; } 380 | .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } 381 | .directory > h3 { margin-top: 0; } 382 | .directory p { margin: 0px; white-space: nowrap; } 383 | .directory div { display: none; margin: 0px; } 384 | .directory img { vertical-align: -30%; } 385 | -------------------------------------------------------------------------------- /doc/build/footer.htm: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /doc/build/header.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pluma - Plug-in Management Framework 5 | 6 | 7 | 8 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /doc/html/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii-huang/pluma/a885b073edd1fd639f9744856092518f94b18f15/doc/html/logo.png -------------------------------------------------------------------------------- /example/PlumaCoreTest/cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.0) 2 | 3 | project(PlumaCoreTest) 4 | 5 | set(PULGIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/plugin) 6 | set(INTERFACE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/interface) 7 | set(MAIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/host) 8 | 9 | include_directories( 10 | ${INTERFACE_DIR} 11 | ${PULGIN_DIR} 12 | ) 13 | 14 | link_libraries(Pluma) 15 | 16 | aux_source_directory(${PULGIN_DIR} ALLSRC) 17 | message(FUNNING ${ALLSRC}) 18 | 19 | #gen plugins 20 | add_library(Eagel SHARED ${PULGIN_DIR}/Eagle.cpp) 21 | add_library(Jaguar SHARED ${PULGIN_DIR}/Jaguar.cpp) 22 | add_library(SimpleWarrior SHARED ${PULGIN_DIR}/SimpleWarrior.cpp) 23 | 24 | #gen manager loader 25 | add_executable(testPlugins ${MAIN_DIR}/main.cpp) 26 | -------------------------------------------------------------------------------- /example/PlumaCoreTest/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PlumaCore.h" 3 | #include "PlumaPipe.h" 4 | 5 | //__PRETTY_FUNCTION__ is mingw definitions print current function name 6 | 7 | class test2 8 | { 9 | public: 10 | test2(){} 11 | 12 | int rihandler(int ar){PDebug() << __PRETTY_FUNCTION__ << ar; return ar*2;} 13 | 14 | void handler(int ar){PDebug() << __PRETTY_FUNCTION__ << ar;} 15 | 16 | void handler(){PDebug()<<__PRETTY_FUNCTION__;} 17 | 18 | void handlerTh1Join(){PDebug()<<__PRETTY_FUNCTION__;} 19 | 20 | void handlerTh2Join(){PDebug() << __PRETTY_FUNCTION__;} 21 | 22 | void handlerTh1Dirc() 23 | { 24 | while(1){PDebug()<<__PRETTY_FUNCTION__;} 25 | } 26 | 27 | void handlerTh2Dirc() 28 | { 29 | while(1){PDebug()<<__PRETTY_FUNCTION__;} 30 | } 31 | 32 | static void shandler(int ar){PDebug() << __PRETTY_FUNCTION__ << ar;} 33 | }; 34 | 35 | 36 | static void testFunc() 37 | { 38 | std::cout << __PRETTY_FUNCTION__ << std::endl; 39 | } 40 | 41 | //argument -Core in Args 42 | static void coreProc(std::string& coreName) 43 | { 44 | std::cout<< __PRETTY_FUNCTION__ << coreName << std::endl; 45 | } 46 | 47 | //argument -Plugin in Args 48 | static void pluginPathProc(std::string& pluginPath) 49 | { 50 | std::cout<< __PRETTY_FUNCTION__ << pluginPath << std::endl; 51 | } 52 | 53 | static void interfaceProc(std::string& interfaces) 54 | { 55 | std::cout<< __PRETTY_FUNCTION__ << interfaces << std::endl; 56 | } 57 | 58 | static void deviceProc(std::string& devices) 59 | { 60 | std::cout<< __PRETTY_FUNCTION__ << devices << std::endl; 61 | } 62 | 63 | /* 0: defualt model is keypress 存在输入提示 64 | * 1: process model not keypress 关闭输入提示 65 | * */ 66 | static int s_RunModel = 0; 67 | static void runmodelProc(std::string& model) 68 | { 69 | if(model == "ShowKeyPress") 70 | s_RunModel = 0; 71 | 72 | if(model == "HideKeyPress") 73 | s_RunModel = 1; 74 | 75 | if(model == "JsonFormat") 76 | s_RunModel = 2; 77 | } 78 | 79 | 80 | 81 | static void readChannel() 82 | { 83 | PDebug()<<__PRETTY_FUNCTION__; 84 | } 85 | 86 | static void writeChannel() 87 | { 88 | PDebug()<<__PRETTY_FUNCTION__; 89 | } 90 | 91 | static void helpChannel() 92 | { 93 | std::map helpInfor; 94 | 95 | helpInfor.insert({ 96 | "help", 97 | "show command help" 98 | }); 99 | 100 | helpInfor.insert({ 101 | "readChannel", 102 | std::string("std::cout from current process out data") + 103 | ", current application: " + 104 | PlumaCore::Application::name() 105 | }); 106 | 107 | helpInfor.insert({ 108 | "writeCahnnel", 109 | std::string("need transfer data to current process") + 110 | ", current application: " + 111 | PlumaCore::Application::name() 112 | }); 113 | 114 | PDebug() << "command help:"; 115 | for(auto val: helpInfor) 116 | { 117 | PDebug() << " " << val.first << " : " << val.second; 118 | } 119 | } 120 | 121 | int main(int argc, char *argv[]) 122 | { 123 | PlumaCore::Application a(argc,argv); 124 | 125 | for(auto var: PlumaCore::Application::arguments()){std::cout << var << std::endl;} 126 | std::cout << "\n" << std::endl; 127 | std::cout << PlumaCore::Application::runPath() << std::endl; 128 | std::cout << PlumaCore::Application::runDir() << std::endl; 129 | std::cout << PlumaCore::Application::name() << std::endl; 130 | 131 | PlumaCore::Application::regArgsCalled("-interface",interfaceProc); 132 | PlumaCore::Application::regArgsCalled("-pluginPath",pluginPathProc); 133 | PlumaCore::Application::regArgsCalled("-core",coreProc); 134 | PlumaCore::Application::regArgsCalled("-devices",deviceProc); 135 | PlumaCore::Application::regArgsCalled("-runModel",runmodelProc); 136 | PlumaCore::Application::argsCall(); 137 | 138 | PDebug() << std::hex << std::uppercase << 255 << 10 << 16; 139 | PDebug() << PlumaCore::Application::argumentMapping(); 140 | PDebug() << PlumaCore::Application::arguments(); 141 | PDebug() << std::hex << std::list{255,10,16}; 142 | PDebug() << std::list{"hhh","ggg","jjj"}; 143 | PDebug() << std::vector{2,3,4}; 144 | 145 | auto foo = [=](){std::cout << __PRETTY_FUNCTION__ << std::endl;}; 146 | 147 | test2 t2; 148 | 149 | std::array classBA = PlumaCore::_ConvtAnyBAToFormat(&t2); 150 | PlumaCore::_ConvtAnyFormatToBA(classBA)->handler(10); 151 | 152 | 153 | std::array handlerBA = PlumaCore::_ConvtAnyBAToFormat(&test2::handler); //类型需要指定否则函数重载将不会被识别 154 | (t2.*PlumaCore::_ConvtAnyFormatToBA(handlerBA))(20); 155 | PlumaCore::Functor(&t2,&test2::handler).call(1000); 156 | 157 | 158 | std::array handlerBA1 = PlumaCore::_ConvtAnyBAToFormat(&test2::handler); //空参数 159 | (t2.*PlumaCore::_ConvtAnyFormatToBA(handlerBA1))(); 160 | PlumaCore::Functor(&t2,&test2::handler).call(); 161 | 162 | 163 | std::array rihandler = PlumaCore::_ConvtAnyBAToFormat(&test2::rihandler); 164 | PDebug() << (t2.*PlumaCore::_ConvtAnyFormatToBA(rihandler))(30) ; 165 | PDebug() << PlumaCore::Functor(&t2,&test2::rihandler).call(100); 166 | 167 | 168 | std::array shandlerBA = PlumaCore::_ConvtAnyBAToFormat(&test2::shandler); //静态函数 169 | (*PlumaCore::_ConvtAnyFormatToBA(shandlerBA))(40); 170 | 171 | (PlumaCore::_ConvtAnyFormatToBA(classBA)->*PlumaCore::_ConvtAnyFormatToBA(handlerBA1))(); //索引调用 172 | 173 | PDebug() << PlumaCore::_SysClassPSize << "|" << PlumaCore::_SysClassFSize; 174 | PDebug() << sizeof(&test2::rihandler); 175 | 176 | PlumaPipe<> pipe; 177 | pipe.connect(&t2,&test2::handler); 178 | pipe.connect(&t2,&test2::handler); 179 | pipe.connect(&t2,&test2::handler); 180 | 181 | pipe.connect(&t2,&test2::handlerTh1Join,PlumaPipe<>::Ct_ThJoined); 182 | pipe.connect(&t2,&test2::handlerTh2Join,PlumaPipe<>::Ct_ThJoined); 183 | 184 | // pipe.connect(&t2,&test2::handlerTh1Dirc,PlumaPipe<>::Ct_ThDirect); 185 | // pipe.connect(&t2,&test2::handlerTh2Dirc,PlumaPipe<>::Ct_ThDirect); 186 | 187 | pipe.send(); 188 | 189 | pipe.disconnect(&t2,&test2::handler); 190 | 191 | pipe.send(); 192 | 193 | PlumaPipe pipe1; 194 | pipe1.connect(&t2,&test2::handler); 195 | pipe1.connect(&t2,&test2::handler); 196 | pipe1.connect(&t2,&test2::handler); 197 | pipe1.send(30); 198 | 199 | //注册交互回调 200 | PlumaCore::Application::regChannelCalled("readChannel",readChannel); 201 | PlumaCore::Application::regChannelCalled("writeChannel",writeChannel); 202 | PlumaCore::Application::regChannelCalled("help",helpChannel); 203 | 204 | PDebug() << "Any channel keypress from :\n" << PlumaCore::Application::channels(); 205 | 206 | while(1) 207 | { 208 | std::string str; 209 | if(0 == s_RunModel) 210 | { 211 | PDebug() << "keypress:"; 212 | } 213 | std::cin >> str; 214 | 215 | if(0 == s_RunModel) 216 | { 217 | PDebug() << "result:" << str; 218 | } 219 | 220 | a.channelCall(str); 221 | } 222 | 223 | return 0; 224 | } 225 | -------------------------------------------------------------------------------- /example/cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.0) 2 | 3 | project(example) 4 | 5 | set(PULGIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/testPlumaPlugins/plugin) 6 | set(INTERFACE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/testPlumaPlugins/interface) 7 | set(LoaderManager_DIR ${CMAKE_CURRENT_SOURCE_DIR}/testPlumaPlugins/loaderManager) 8 | set(PlumaCore_DIR ${CMAKE_CURRENT_SOURCE_DIR}/testPlumaCore) 9 | 10 | set(CMAKE_CXX_STANDARD 11) 11 | 12 | include_directories( 13 | ${INTERFACE_DIR} 14 | ${PULGIN_DIR} 15 | ) 16 | 17 | link_libraries(Pluma) 18 | 19 | 20 | 21 | aux_source_directory(${PULGIN_DIR} tPlumaPluginsSRC) 22 | message(FUNNING ${tPlumaPluginsSRC}) 23 | 24 | #gen plugins 25 | add_library(Eagel SHARED ${PULGIN_DIR}/Eagle.cpp) 26 | add_library(Jaguar SHARED ${PULGIN_DIR}/Jaguar.cpp) 27 | add_library(SimpleWarrior SHARED ${PULGIN_DIR}/SimpleWarrior.cpp) 28 | 29 | #gen manager loader 30 | add_executable(tPluginLoader ${LoaderManager_DIR}/main.cpp) 31 | 32 | #gen plumaCore load has channel callback 33 | add_executable(tPlumaCore ${PlumaCore_DIR}/main.cpp) -------------------------------------------------------------------------------- /example/src/host/main.cpp: -------------------------------------------------------------------------------- 1 | #include //static link library head 2 | #include "Warrior.hpp" //interface head 3 | #include 4 | 5 | int main(int argc,char* argv[]) 6 | { 7 | pluma::Pluma pluma; 8 | pluma.acceptProviderType(); 9 | 10 | // // Add a default warrior provider 11 | // pluma.addProvider(new SimpleWarriorProvider() ); 12 | 13 | // Load libraries 14 | std::cout<<"load plugin number:"<< pluma.loadFromFolder("./") << std::endl; 15 | 16 | // Get warrior providers into a vector 17 | std::vector providers; 18 | pluma.getProviders(providers); 19 | 20 | // Create a Warrior from each provider 21 | std::vector::iterator it; 22 | for (it = providers.begin() ; it != providers.end() ; ++it){ 23 | // Create a warrior 24 | Warrior* warrior = (*it)->create(); 25 | // Display it's description 26 | std::cout << warrior->getDescription() << std::endl; 27 | // (...) 28 | // don't forget to delete it 29 | delete warrior; 30 | } 31 | pluma.unloadAll(); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /example/src/interface/Warrior.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WARRIOR_HPP 2 | #define WARRIOR_HPP 3 | 4 | #include 5 | 6 | ///////////////////////////////////////////////////////// 7 | /// Warrior Interface 8 | /// That's the kind of objects that plugins will provide. 9 | ///////////////////////////////////////////////////////// 10 | class Warrior{ 11 | public: 12 | virtual std::string getDescription() = 0; 13 | // (...) 14 | }; 15 | 16 | 17 | ///////////////////////////////////////////////////////// 18 | /// WarriorProvider Interface 19 | /// Plugins will provide host with new Warriors throgh WarriorProvider 20 | /// implementations. Host automatically check version compatibility. 21 | ///////////////////////////////////////////////////////// 22 | // PLUMA_GEN_PROVIDER(Type, current_version, lowest_compatible_version) 23 | PLUMA_PROVIDER_HEADER(Warrior); 24 | PLUMA_PROVIDER_SOURCE(Warrior, 1, 1); 25 | 26 | // - Advanced example of provider header generation 27 | //PLUMA_PROVIDER_HEADER_BEGIN(Warrior) 28 | // public: 29 | // virtual Warrior* create(int energy) = 0; 30 | // virtual void populate(std::vector& army, int numSoldiers) = 0; 31 | //PLUMA_PROVIDER_HEADER_END 32 | 33 | 34 | #endif // WARRIOR_HPP 35 | -------------------------------------------------------------------------------- /example/src/plugin/Eagle.cpp: -------------------------------------------------------------------------------- 1 | #include "Eagle.hpp" 2 | 3 | std::string Eagle::getDescription() 4 | { 5 | return "Eagle Warrior: soldier of the sun"; 6 | } 7 | -------------------------------------------------------------------------------- /example/src/plugin/Eagle.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EAGLE_HPP 2 | #define EAGLE_HPP 3 | 4 | #include "Warrior.hpp" 5 | #include 6 | 7 | ///////////////////////////////////////////////////////// 8 | /// An Eagle is a Warrior 9 | ///////////////////////////////////////////////////////// 10 | class Eagle: public Warrior{ 11 | public: 12 | std::string getDescription(); 13 | }; 14 | 15 | ///////////////////////////////////////////////////////// 16 | /// An EagleProvider is a WarriorProvider, 17 | /// provide warriors of type Eagle 18 | ///////////////////////////////////////////////////////// 19 | PLUMA_INHERIT_PROVIDER(Eagle, Warrior); 20 | 21 | PLUMA_CONNECTOR bool connect(pluma::Host& host){ host.add( new EagleProvider() ); return true;} 22 | 23 | #endif // EAGLE_HPP 24 | -------------------------------------------------------------------------------- /example/src/plugin/Jaguar.cpp: -------------------------------------------------------------------------------- 1 | #include "jaguar.hpp" 2 | 3 | std::string Jaguar::getDescription() 4 | { 5 | return "Jaguar Warrior: soldier of Tezcatlipoca"; 6 | } -------------------------------------------------------------------------------- /example/src/plugin/Jaguar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAGUAR_HPP 2 | #define JAGUAR_HPP 3 | 4 | #include "Warrior.hpp" 5 | #include 6 | 7 | ///////////////////////////////////////////////////////// 8 | /// A Jaguar is a Warrior 9 | ///////////////////////////////////////////////////////// 10 | class Jaguar: public Warrior{ 11 | public: 12 | std::string getDescription(); 13 | }; 14 | 15 | ///////////////////////////////////////////////////////// 16 | /// A JaguarProvider is a WarriorProvider, 17 | /// provide warriors of type Jaguar 18 | ///////////////////////////////////////////////////////// 19 | PLUMA_INHERIT_PROVIDER(Jaguar, Warrior); 20 | 21 | PLUMA_CONNECTOR bool connect(pluma::Host& host){ host.add( new JaguarProvider() ); return true;} 22 | 23 | #endif // JAGUAR_HPP 24 | -------------------------------------------------------------------------------- /example/src/plugin/SimpleWarrior.cpp: -------------------------------------------------------------------------------- 1 | #include "SimpleWarrior.hpp" 2 | 3 | std::string SimpleWarrior::getDescription() 4 | { 5 | return "Commoner: leaded by calpoleque"; 6 | } 7 | -------------------------------------------------------------------------------- /example/src/plugin/SimpleWarrior.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLE_WARRIOR_HPP 2 | #define SIMPLE_WARRIOR_HPP 3 | 4 | #include "Warrior.hpp" 5 | #include 6 | 7 | ///////////////////////////////////////////////////////// 8 | /// Default Warrior 9 | ///////////////////////////////////////////////////////// 10 | class SimpleWarrior: public Warrior{ 11 | public: 12 | std::string getDescription(); 13 | }; 14 | 15 | ///////////////////////////////////////////////////////// 16 | /// SimpleWarriorProvider provide default warriors 17 | ///////////////////////////////////////////////////////// 18 | PLUMA_INHERIT_PROVIDER(SimpleWarrior, Warrior); 19 | 20 | PLUMA_CONNECTOR bool connect(pluma::Host& host){ host.add( new SimpleWarriorProvider() ); return true;} 21 | 22 | #endif // SIMPLE_WARRIOR_HPP 23 | -------------------------------------------------------------------------------- /example/testPlumaCore/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PlumaCore.hpp" 3 | #include "PlumaPipe.hpp" 4 | 5 | class test2 6 | { 7 | public: 8 | test2(){} 9 | 10 | int rihandler(int ar){PDebug() << FUNCTION_INFO << ar; return ar*2;} 11 | 12 | void handler(int ar){PDebug() << FUNCTION_INFO << ar;} 13 | 14 | void handler(){PDebug()<< FUNCTION_INFO;} 15 | 16 | void handlerTh1Join(){PDebug()<< FUNCTION_INFO;} 17 | 18 | void handlerTh2Join(){PDebug() << FUNCTION_INFO;} 19 | 20 | void handlerTh1Dirc() 21 | { 22 | while(1){PDebug()<< FUNCTION_INFO;} 23 | } 24 | 25 | void handlerTh2Dirc() 26 | { 27 | while(1){PDebug()<< FUNCTION_INFO;} 28 | } 29 | 30 | static void shandler(int ar){PDebug() << FUNCTION_INFO << ar;} 31 | }; 32 | 33 | 34 | static void testFunc() 35 | { 36 | std::cout << FUNCTION_INFO << std::endl; 37 | } 38 | 39 | //argument -Core in Args 40 | static void coreProc(std::string& coreName) 41 | { 42 | std::cout<< FUNCTION_INFO << coreName << std::endl; 43 | } 44 | 45 | //argument -Plugin in Args 46 | static void pluginPathProc(std::string& pluginPath) 47 | { 48 | std::cout<< FUNCTION_INFO << pluginPath << std::endl; 49 | } 50 | 51 | static void interfaceProc(std::string& interfaces) 52 | { 53 | std::cout<< FUNCTION_INFO << interfaces << std::endl; 54 | } 55 | 56 | static void deviceProc(std::string& devices) 57 | { 58 | std::cout<< FUNCTION_INFO << devices << std::endl; 59 | } 60 | 61 | /* 0: defualt model is keypress 存在输入提示 62 | * 1: process model not keypress 关闭输入提示 63 | * */ 64 | static int s_RunModel = 0; 65 | static void runmodelProc(std::string& model) 66 | { 67 | if(model == "ShowKeyPress") 68 | s_RunModel = 0; 69 | 70 | if(model == "HideKeyPress") 71 | s_RunModel = 1; 72 | 73 | if(model == "JsonFormat") 74 | s_RunModel = 2; 75 | } 76 | 77 | 78 | 79 | static void readChannel() 80 | { 81 | PDebug()<< FUNCTION_INFO; 82 | } 83 | 84 | static void writeChannel() 85 | { 86 | PDebug()<< FUNCTION_INFO; 87 | } 88 | 89 | static void helpChannel() 90 | { 91 | std::map helpInfor; 92 | 93 | helpInfor.insert({ 94 | "help", 95 | "show command help" 96 | }); 97 | 98 | helpInfor.insert({ 99 | "readChannel", 100 | std::string("std::cout from current process out data") + 101 | ", current application: " + 102 | PlumaCore::Application::name() 103 | }); 104 | 105 | helpInfor.insert({ 106 | "writeCahnnel", 107 | std::string("need transfer data to current process") + 108 | ", current application: " + 109 | PlumaCore::Application::name() 110 | }); 111 | 112 | PDebug() << "command help:"; 113 | for(auto val: helpInfor) 114 | { 115 | PDebug() << " " << val.first << " : " << val.second; 116 | } 117 | } 118 | 119 | int main(int argc, char *argv[]) 120 | { 121 | PlumaCore::Application a(argc,argv); 122 | 123 | for(auto var: PlumaCore::Application::arguments()){std::cout << var << std::endl;} 124 | std::cout << "\n" << std::endl; 125 | std::cout << PlumaCore::Application::runPath() << std::endl; 126 | std::cout << PlumaCore::Application::runDir() << std::endl; 127 | std::cout << PlumaCore::Application::name() << std::endl; 128 | 129 | PlumaCore::Application::regArgsCalled("-interface",interfaceProc); 130 | PlumaCore::Application::regArgsCalled("-pluginPath",pluginPathProc); 131 | PlumaCore::Application::regArgsCalled("-core",coreProc); 132 | PlumaCore::Application::regArgsCalled("-devices",deviceProc); 133 | PlumaCore::Application::regArgsCalled("-runModel",runmodelProc); 134 | PlumaCore::Application::argsCall(); 135 | 136 | PDebug() << std::hex << std::uppercase << 255 << 10 << 16; 137 | PDebug() << PlumaCore::Application::argumentMapping(); 138 | PDebug() << PlumaCore::Application::arguments(); 139 | PDebug() << std::hex << std::list{255,10,16}; 140 | PDebug() << std::list{"hhh","ggg","jjj"}; 141 | PDebug() << std::vector{2,3,4}; 142 | 143 | auto foo = [=](){std::cout << FUNCTION_INFO << std::endl;}; 144 | 145 | test2 t2; 146 | 147 | class varient: std::array 148 | { 149 | 150 | }; 151 | 152 | std::array CBaseAddress = PlumaCore::_ConvtAnyBAToFormat(&t2); 153 | PlumaCore::_ConvtAnyFormatToBA(CBaseAddress)->handler(10); 154 | 155 | std::array handlerBA = PlumaCore::_ConvtAnyBAToFormat(&test2::handler); //类型需要指定否则函数重载将不会被识别 156 | (t2.*PlumaCore::_ConvtAnyFormatToBA(handlerBA))(20); 157 | PlumaCore::Functor(&t2,&test2::handler).call(1000); 158 | 159 | 160 | std::array handlerBA1 = PlumaCore::_ConvtAnyBAToFormat(&test2::handler); //空参数 161 | (t2.*PlumaCore::_ConvtAnyFormatToBA(handlerBA1))(); 162 | PlumaCore::Functor(&t2,&test2::handler).call(); 163 | 164 | 165 | std::array rihandler = PlumaCore::_ConvtAnyBAToFormat(&test2::rihandler); 166 | PDebug() << (t2.*PlumaCore::_ConvtAnyFormatToBA(rihandler))(30) ; 167 | PDebug() << PlumaCore::Functor(&t2,&test2::rihandler).call(100); 168 | 169 | 170 | std::array shandlerBA = PlumaCore::_ConvtAnyBAToFormat(&test2::shandler); //静态函数 171 | (*PlumaCore::_ConvtAnyFormatToBA(shandlerBA))(40); 172 | (PlumaCore::_ConvtAnyFormatToBA(CBaseAddress)->*PlumaCore::_ConvtAnyFormatToBA(handlerBA1))(); //索引调用 173 | 174 | PDebug() << PlumaCore::_SysClassPSize << "|" << PlumaCore::_SysClassFSize; 175 | PDebug() << sizeof(&test2::rihandler); 176 | 177 | PlumaPipe<> pipe; 178 | pipe.connect(&t2,&test2::handler); 179 | pipe.connect(&t2,&test2::handler); 180 | pipe.connect(&t2,&test2::handler); 181 | 182 | pipe.connect(&t2,&test2::handlerTh1Join,PlumaPipe<>::Ct_ThJoined); 183 | pipe.connect(&t2,&test2::handlerTh2Join,PlumaPipe<>::Ct_ThJoined); 184 | 185 | // pipe.connect(&t2,&test2::handlerTh1Dirc,PlumaPipe<>::Ct_ThDirect); 186 | // pipe.connect(&t2,&test2::handlerTh2Dirc,PlumaPipe<>::Ct_ThDirect); 187 | 188 | pipe.send(); 189 | 190 | pipe.disconnect(&t2,&test2::handler); 191 | 192 | pipe.send(); 193 | 194 | PlumaPipe pipe1; 195 | pipe1.connect(&t2,&test2::handler); 196 | pipe1.connect(&t2,&test2::handler); 197 | pipe1.connect(&t2,&test2::handler); 198 | pipe1.send(30); 199 | 200 | //注册交互回调 201 | PlumaCore::Application::regChannelCalled("readChannel",readChannel); 202 | PlumaCore::Application::regChannelCalled("writeChannel",writeChannel); 203 | PlumaCore::Application::regChannelCalled("help",helpChannel); 204 | 205 | PDebug() << "Any channel keypress from :\n" << PlumaCore::Application::channels(); 206 | 207 | while(1) 208 | { 209 | std::string str; 210 | PDebug() << ">"; 211 | std::cin >> str; 212 | a.channelCall(str); 213 | } 214 | return 0; 215 | } 216 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/interface/Warrior.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WARRIOR_HPP 2 | #define WARRIOR_HPP 3 | 4 | #include 5 | 6 | ///////////////////////////////////////////////////////// 7 | /// Warrior Interface 8 | /// That's the kind of objects that plugins will provide. 9 | ///////////////////////////////////////////////////////// 10 | class Warrior{ 11 | public: 12 | virtual std::string getDescription() = 0; 13 | // (...) 14 | }; 15 | 16 | 17 | ///////////////////////////////////////////////////////// 18 | /// WarriorProvider Interface 19 | /// Plugins will provide host with new Warriors throgh WarriorProvider 20 | /// implementations. Host automatically check version compatibility. 21 | ///////////////////////////////////////////////////////// 22 | // PLUMA_GEN_PROVIDER(Type, current_version, lowest_compatible_version) 23 | PLUMA_PROVIDER_HEADER(Warrior); 24 | PLUMA_PROVIDER_SOURCE(Warrior, 1, 1); 25 | 26 | // - Advanced example of provider header generation 27 | //PLUMA_PROVIDER_HEADER_BEGIN(Warrior) 28 | // public: 29 | // virtual Warrior* create(int energy) = 0; 30 | // virtual void populate(std::vector& army, int numSoldiers) = 0; 31 | //PLUMA_PROVIDER_HEADER_END 32 | 33 | 34 | #endif // WARRIOR_HPP 35 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/loaderManager/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Warrior.hpp" 3 | #include 4 | 5 | int main(int argc,char* argv[]) 6 | { 7 | pluma::Pluma pluma; 8 | pluma.acceptProviderType(); 9 | 10 | // // Add a default warrior provider 11 | // pluma.addProvider(new SimpleWarriorProvider() ); 12 | 13 | // Load libraries 14 | std::cout<<"load plugin number:"<< pluma.loadFromFolder("./") << std::endl; 15 | 16 | // Get warrior providers into a vector 17 | std::vector providers; 18 | pluma.getProviders(providers); 19 | 20 | // Create a Warrior from each provider 21 | std::vector::iterator it; 22 | for (it = providers.begin() ; it != providers.end() ; ++it){ 23 | // Create a warrior 24 | Warrior* warrior = (*it)->create(); 25 | // Display it's description 26 | std::cout << warrior->getDescription() << std::endl; 27 | // (...) 28 | // don't forget to delete it 29 | delete warrior; 30 | } 31 | pluma.unloadAll(); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/plugin/Eagle.cpp: -------------------------------------------------------------------------------- 1 | #include "Eagle.hpp" 2 | 3 | std::string Eagle::getDescription() 4 | { 5 | return "Eagle Warrior: soldier of the sun"; 6 | } 7 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/plugin/Eagle.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EAGLE_HPP 2 | #define EAGLE_HPP 3 | 4 | #include "Warrior.hpp" 5 | #include 6 | 7 | ///////////////////////////////////////////////////////// 8 | /// An Eagle is a Warrior 9 | ///////////////////////////////////////////////////////// 10 | class Eagle: public Warrior{ 11 | public: 12 | std::string getDescription(); 13 | }; 14 | 15 | ///////////////////////////////////////////////////////// 16 | /// An EagleProvider is a WarriorProvider, 17 | /// provide warriors of type Eagle 18 | ///////////////////////////////////////////////////////// 19 | PLUMA_INHERIT_PROVIDER(Eagle, Warrior); 20 | 21 | PLUMA_CONNECTOR bool connect(pluma::Host& host){ host.add( new EagleProvider() ); return true;} 22 | 23 | #endif // EAGLE_HPP 24 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/plugin/Jaguar.cpp: -------------------------------------------------------------------------------- 1 | #include "jaguar.hpp" 2 | 3 | std::string Jaguar::getDescription() 4 | { 5 | return "Jaguar Warrior: soldier of Tezcatlipoca"; 6 | } -------------------------------------------------------------------------------- /example/testPlumaPlugins/plugin/Jaguar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAGUAR_HPP 2 | #define JAGUAR_HPP 3 | 4 | #include "Warrior.hpp" 5 | #include 6 | 7 | ///////////////////////////////////////////////////////// 8 | /// A Jaguar is a Warrior 9 | ///////////////////////////////////////////////////////// 10 | class Jaguar: public Warrior{ 11 | public: 12 | std::string getDescription(); 13 | }; 14 | 15 | ///////////////////////////////////////////////////////// 16 | /// A JaguarProvider is a WarriorProvider, 17 | /// provide warriors of type Jaguar 18 | ///////////////////////////////////////////////////////// 19 | PLUMA_INHERIT_PROVIDER(Jaguar, Warrior); 20 | 21 | PLUMA_CONNECTOR bool connect(pluma::Host& host){ host.add( new JaguarProvider() ); return true;} 22 | 23 | #endif // JAGUAR_HPP 24 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/plugin/SimpleWarrior.cpp: -------------------------------------------------------------------------------- 1 | #include "SimpleWarrior.hpp" 2 | 3 | std::string SimpleWarrior::getDescription() 4 | { 5 | return "Commoner: leaded by calpoleque"; 6 | } 7 | -------------------------------------------------------------------------------- /example/testPlumaPlugins/plugin/SimpleWarrior.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLE_WARRIOR_HPP 2 | #define SIMPLE_WARRIOR_HPP 3 | 4 | #include "Warrior.hpp" 5 | #include 6 | 7 | ///////////////////////////////////////////////////////// 8 | /// Default Warrior 9 | ///////////////////////////////////////////////////////// 10 | class SimpleWarrior: public Warrior{ 11 | public: 12 | std::string getDescription(); 13 | }; 14 | 15 | ///////////////////////////////////////////////////////// 16 | /// SimpleWarriorProvider provide default warriors 17 | ///////////////////////////////////////////////////////// 18 | PLUMA_INHERIT_PROVIDER(SimpleWarrior, Warrior); 19 | 20 | PLUMA_CONNECTOR bool connect(pluma::Host& host){ host.add( new SimpleWarriorProvider() ); return true;} 21 | 22 | #endif // SIMPLE_WARRIOR_HPP 23 | -------------------------------------------------------------------------------- /include/Pluma/Config.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | // 28 | // Based on SFML configuration header 29 | // SFML Config.hpp: 30 | // http://www.sfml-dev.org/documentation/2.0/Config_8hpp-source.htm 31 | // 32 | // Acknowledgements to Simple and Fast Multimedia Library 33 | // http://www.sfml-dev.org/ 34 | // 35 | //////////////////////////////////////////////////////////// 36 | 37 | 38 | #ifndef PLUMA_CONFIG_HPP 39 | #define PLUMA_CONFIG_HPP 40 | 41 | 42 | //////////////////////////////////////////////////////////// 43 | // Identify the operating system 44 | //////////////////////////////////////////////////////////// 45 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) 46 | 47 | // Windows 48 | #define PLUMA_SYS_WINDOWS 49 | #ifndef WIN32_LEAN_AND_MEAN 50 | #define WIN32_LEAN_AND_MEAN 51 | #endif 52 | #ifndef NOMINMAX 53 | #define NOMINMAX 54 | #endif 55 | 56 | #elif defined(linux) || defined(__linux) 57 | 58 | // Linux 59 | #define PLUMA_SYS_LINUX 60 | 61 | #elif defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh) 62 | 63 | // MacOS 64 | #define PLUMA_SYS_MACOS 65 | 66 | #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 67 | 68 | // FreeBSD 69 | #define PLUMA_SYS_FREEBSD 70 | 71 | #else 72 | 73 | // Unsupported system 74 | #error This operating system is not supported by this library 75 | 76 | #endif 77 | 78 | 79 | 80 | //////////////////////////////////////////////////////////// 81 | // Define library file extension based on OS 82 | //////////////////////////////////////////////////////////// 83 | #ifdef PLUMA_SYS_WINDOWS 84 | #define PLUMA_LIB_EXTENSION "dll" 85 | #elif defined(PLUMA_SYS_MACOS) 86 | #define PLUMA_LIB_EXTENSION "dylib" 87 | #elif defined(PLUMA_SYS_LINUX) || defined(PLUMA_SYS_FREEBSD) 88 | #define PLUMA_LIB_EXTENSION "so" 89 | #else 90 | // unknown library file type 91 | #error Unknown library file extension for this operating system 92 | #endif 93 | 94 | 95 | //////////////////////////////////////////////////////////// 96 | // Define portable import / export macros 97 | //////////////////////////////////////////////////////////// 98 | #if defined(PLUMA_SYS_WINDOWS) 99 | 100 | #ifndef PLUMA_STATIC 101 | 102 | // Windows platforms 103 | #ifdef PLUMA_EXPORTS 104 | 105 | // From DLL side, we must export 106 | #define PLUMA_API __declspec(dllexport) 107 | 108 | #else 109 | 110 | // From client application side, we must import 111 | #define PLUMA_API __declspec(dllimport) 112 | 113 | #endif 114 | 115 | // For Visual C++ compilers, we also need to turn off this annoying C4251 warning. 116 | // You can read lots ot different things about it, but the point is the code will 117 | // just work fine, and so the simplest way to get rid of this warning is to disable it 118 | #ifdef _MSC_VER 119 | 120 | #pragma warning(disable : 4251) 121 | 122 | #endif 123 | 124 | #else 125 | 126 | // No specific directive needed for static build 127 | #define PLUMA_API 128 | 129 | #endif 130 | 131 | #else 132 | 133 | // Other platforms don't need to define anything 134 | #define PLUMA_API 135 | 136 | #endif 137 | 138 | 139 | 140 | 141 | #endif // PLUMA_CONFIG_HPP 142 | -------------------------------------------------------------------------------- /include/Pluma/Connector.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_CONNECTOR_HPP 26 | #define PLUMA_CONNECTOR_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | 34 | 35 | ///////////////////////////////////////////////////////////////// 36 | // Define portable import/export macros for Plugin registration 37 | ///////////////////////////////////////////////////////////////// 38 | #if defined(PLUMA_SYS_WINDOWS) 39 | 40 | #ifndef PLUMA_STATIC_PLUGIN 41 | 42 | // Windows platforms 43 | #ifndef PLUGIN_IMPORTS 44 | 45 | // From DLL side, we must export 46 | #ifdef __cplusplus 47 | #define PLUMA_CONNECTOR extern "C" __declspec(dllexport) 48 | #else 49 | #define PLUMA_CONNECTOR __declspec(dllexport) 50 | #endif 51 | 52 | #else 53 | 54 | // From client application side, we must import 55 | #ifdef __cplusplus 56 | #define PLUMA_CONNECTOR extern "C" __declspec(dllimport) 57 | #else 58 | #define PLUMA_CONNECTOR __declspec(dllimport) 59 | #endif 60 | 61 | #endif 62 | 63 | #else 64 | 65 | // Only define the extern "C" for static build 66 | #ifdef __cplusplus 67 | #define PLUMA_CONNECTOR extern "C" 68 | #else 69 | #define PLUMA_CONNECTOR 70 | #endif 71 | 72 | #endif 73 | 74 | #else 75 | 76 | // Only define the extern "C" for other platforms 77 | #ifdef __cplusplus 78 | #define PLUMA_CONNECTOR extern "C" 79 | #else 80 | #define PLUMA_CONNECTOR 81 | #endif 82 | 83 | #endif 84 | 85 | 86 | #endif // PLUMA_CONNECTOR_HPP 87 | -------------------------------------------------------------------------------- /include/Pluma/Host.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_HOST_HPP 26 | #define PLUMA_HOST_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | namespace pluma{ 39 | 40 | //////////////////////////////////////////////////////////// 41 | /// \brief Manages providers. 42 | /// 43 | //////////////////////////////////////////////////////////// 44 | class PLUMA_API Host{ 45 | friend class PluginManager; 46 | friend class Provider; 47 | 48 | 49 | public: 50 | 51 | //////////////////////////////////////////////////////////// 52 | /// \brief Add provider. 53 | /// 54 | /// Provider type and version are checked. Only known and 55 | /// valid provider types are accepted. 56 | /// 57 | /// \param provider Provider to be added. 58 | /// 59 | /// \return True if the provider is accepted. 60 | /// 61 | //////////////////////////////////////////////////////////// 62 | bool add(Provider* provider); 63 | 64 | 65 | private: 66 | 67 | //////////////////////////////////////////////////////////// 68 | /// \brief Default constructor. 69 | /// 70 | /// New Host instances are not publicly allowed. 71 | /// 72 | //////////////////////////////////////////////////////////// 73 | Host(); 74 | 75 | //////////////////////////////////////////////////////////// 76 | /// \brief Destructor. 77 | /// 78 | /// Clears all hosted providers 79 | /// 80 | //////////////////////////////////////////////////////////// 81 | ~Host(); 82 | 83 | //////////////////////////////////////////////////////////// 84 | /// \brief Ckeck if a provider type is registered. 85 | /// 86 | /// \param type Provider type id. 87 | /// 88 | /// \return True if the type is registered 89 | /// 90 | //////////////////////////////////////////////////////////// 91 | bool knows(const std::string& type) const; 92 | 93 | //////////////////////////////////////////////////////////// 94 | /// \brief Get version of a type of providers. 95 | /// 96 | /// \param type Provider type. 97 | /// 98 | /// \return The version of the provider type. 99 | /// 100 | //////////////////////////////////////////////////////////// 101 | unsigned int getVersion(const std::string& type) const; 102 | 103 | //////////////////////////////////////////////////////////// 104 | /// \brief Get lowest compatible version of a type of providers. 105 | /// 106 | /// \param type Provider type. 107 | /// 108 | /// \return The lowest compatible version of the provider type. 109 | /// 110 | //////////////////////////////////////////////////////////// 111 | unsigned int getLowestVersion(const std::string& type) const; 112 | 113 | //////////////////////////////////////////////////////////// 114 | /// \brief Register a type of providers. 115 | /// 116 | /// \param type Provider type. 117 | /// \param version Current version of that provider type. 118 | /// \param lowestVersion Lowest compatible version of that provider type. 119 | /// 120 | //////////////////////////////////////////////////////////// 121 | void registerType(const std::string& type, unsigned int version, unsigned int lowestVersion); 122 | 123 | //////////////////////////////////////////////////////////// 124 | /// \brief Get providers of a certain type. 125 | /// 126 | /// \param type Provider type. 127 | /// 128 | /// \return Pointer to the list of providers of that \a type, 129 | /// or NULL if \a type is not registered. 130 | /// 131 | //////////////////////////////////////////////////////////// 132 | const std::list* getProviders(const std::string& type) const; 133 | 134 | //////////////////////////////////////////////////////////// 135 | /// \brief Clears all hosted providers. 136 | /// 137 | //////////////////////////////////////////////////////////// 138 | void clearProviders(); 139 | 140 | //////////////////////////////////////////////////////////// 141 | /// \brief Validate provider type and version. 142 | /// 143 | /// \return True if the provider is acceptable. 144 | /// 145 | //////////////////////////////////////////////////////////// 146 | bool validateProvider(Provider* provider) const; 147 | 148 | //////////////////////////////////////////////////////////// 149 | /// \brief Clearly add a provider. 150 | /// 151 | /// Provider type and version are checked. Only known and 152 | /// valid provider types are accepted. 153 | /// If acepted, provider is directly stored. 154 | /// 155 | /// \param provider Provider to be added. 156 | /// 157 | /// \return True if the provider is accepted. 158 | /// 159 | //////////////////////////////////////////////////////////// 160 | bool registerProvider(Provider* provider); 161 | 162 | //////////////////////////////////////////////////////////// 163 | /// \brief Previous add calls are canceled. 164 | /// 165 | /// Added providers are not stored. 166 | /// 167 | /// \see add 168 | /// 169 | //////////////////////////////////////////////////////////// 170 | void cancelAddictions(); 171 | 172 | //////////////////////////////////////////////////////////// 173 | /// \brief Previous add calls are confirmed. 174 | /// 175 | /// Added providers are finally stored. 176 | /// 177 | /// \return True if something was stored. 178 | /// 179 | /// \see add 180 | /// 181 | //////////////////////////////////////////////////////////// 182 | bool confirmAddictions(); 183 | 184 | 185 | 186 | //////////////////////////////////////////////////////////// 187 | // Member data 188 | //////////////////////////////////////////////////////////// 189 | 190 | private: 191 | 192 | //////////////////////////////////////////////////////////// 193 | /// \brief Structure with information about a provider type. 194 | /// 195 | //////////////////////////////////////////////////////////// 196 | struct ProviderInfo{ 197 | unsigned int version; 198 | unsigned int lowestVersion; 199 | std::list providers; 200 | }; 201 | 202 | typedef std::map ProvidersMap; 203 | typedef std::map > TempProvidersMap; 204 | 205 | ProvidersMap knownTypes; ///< Map of registered types. 206 | TempProvidersMap addRequests; ///< Temporarily added providers 207 | 208 | }; 209 | 210 | } // namespace pluma 211 | 212 | #endif // PLUMA_HOST_HPP 213 | -------------------------------------------------------------------------------- /include/Pluma/PluginManager.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_PLUGIN_MANAGER_HPP 26 | #define PLUMA_PLUGIN_MANAGER_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | namespace pluma{ 38 | class DLibrary; 39 | 40 | //////////////////////////////////////////////////////////// 41 | /// \brief Manages loaded plugins. 42 | /// 43 | //////////////////////////////////////////////////////////// 44 | class PLUMA_API PluginManager{ 45 | 46 | 47 | public: 48 | 49 | //////////////////////////////////////////////////////////// 50 | /// \brief Destructor. 51 | /// 52 | //////////////////////////////////////////////////////////// 53 | ~PluginManager(); 54 | 55 | //////////////////////////////////////////////////////////// 56 | /// \brief Load a plugin given it's path 57 | /// 58 | /// \param path Path for the plugin, including plugin name. File extension 59 | /// may be included, but is discouraged for better cross platform code. 60 | /// If file extension isn't present on the path, Pluma will deduce it 61 | /// from the operating system. 62 | /// 63 | /// \return True if the plugin is successfully loaded. 64 | /// 65 | /// \see load(const std::string&, const std::string&) 66 | /// \see loadFromFolder 67 | /// \see unload 68 | /// \see unloadAll 69 | /// 70 | //////////////////////////////////////////////////////////// 71 | bool load(const std::string& path); 72 | 73 | 74 | //////////////////////////////////////////////////////////// 75 | /// \brief Load a plugin from a given folder 76 | /// 77 | /// \param folder The folder path. 78 | /// \param pluginName Name of the plugin. File extension 79 | /// may be included, but is discouraged for better cross platform code. 80 | /// If file extension is omitted, Pluma will deduce it 81 | /// from the operating system. 82 | /// 83 | /// \return True if the plugin is successfully loaded. 84 | /// 85 | /// \see load(const std::string&) 86 | /// \see loadFromFolder 87 | /// \see unload 88 | /// \see unloadAll 89 | /// 90 | //////////////////////////////////////////////////////////// 91 | bool load(const std::string& folder, const std::string& pluginName); 92 | 93 | //////////////////////////////////////////////////////////// 94 | /// \brief Load all plugins from a given folder 95 | /// 96 | /// \param folder Path for the folder where the plug-ins are. 97 | /// \param recursive If true it will search on sub-folders as well 98 | /// 99 | /// \return Number of successfully loaded plug-ins. 100 | /// 101 | /// \see load(const std::string&, const std::string&) 102 | /// \see load(const std::string&) 103 | /// \see unload 104 | /// \see unloadAll 105 | /// 106 | //////////////////////////////////////////////////////////// 107 | int loadFromFolder(const std::string& folder, bool recursive = false); 108 | 109 | //////////////////////////////////////////////////////////// 110 | /// \brief Unload a plugin. 111 | /// 112 | /// \param pluginName Name or path of the plugin. 113 | /// 114 | /// \return True if the plugin is successfully unloaded, 115 | /// false if no such plugin exists on the manager. 116 | /// 117 | /// \see load(const std::string&, const std::string&) 118 | /// \see load(const std::string&) 119 | /// \see loadFromFolder 120 | /// \see unloadAll 121 | /// 122 | //////////////////////////////////////////////////////////// 123 | bool unload(const std::string& pluginName); 124 | 125 | //////////////////////////////////////////////////////////// 126 | /// \brief Unload all loaded plugins. 127 | /// 128 | /// \see load(const std::string&, const std::string&) 129 | /// \see load(const std::string&) 130 | /// \see loadFromFolder 131 | /// \see unload 132 | /// 133 | //////////////////////////////////////////////////////////// 134 | void unloadAll(); 135 | 136 | //////////////////////////////////////////////////////////// 137 | /// \brief Directly add a new provider. 138 | /// 139 | /// \param provider Provider. 140 | /// 141 | //////////////////////////////////////////////////////////// 142 | bool addProvider(Provider* provider); 143 | 144 | //////////////////////////////////////////////////////////// 145 | /// \brief Get the name of all loaded plugins. 146 | /// 147 | /// \param pluginNames A vector to fill with the plugins names. 148 | /// 149 | //////////////////////////////////////////////////////////// 150 | void getLoadedPlugins(std::vector& pluginNames) const; 151 | 152 | //////////////////////////////////////////////////////////// 153 | /// \brief Check if a plug-in is loaded. 154 | /// 155 | /// \param pluginName the plug-in tname o check. 156 | /// 157 | //////////////////////////////////////////////////////////// 158 | bool isLoaded(const std::string& pluginName) const; 159 | 160 | 161 | protected: 162 | 163 | //////////////////////////////////////////////////////////// 164 | /// \brief Default constructor. 165 | /// 166 | /// PluginManager cannot be publicly instantiated. 167 | /// 168 | //////////////////////////////////////////////////////////// 169 | PluginManager(); 170 | 171 | //////////////////////////////////////////////////////////// 172 | /// \brief Register a provider type 173 | /// 174 | /// \param type Provider type. 175 | /// \param version Current version of that provider type. 176 | /// \param lowestVersion Lowest compatible version of that provider type. 177 | /// 178 | /// \see Host::registerType 179 | /// 180 | //////////////////////////////////////////////////////////// 181 | void registerType(const std::string& type, unsigned int version, unsigned int lowestVersion); 182 | 183 | //////////////////////////////////////////////////////////// 184 | /// \brief Get providers of a certain type. 185 | /// 186 | /// \param type Provider type. 187 | /// 188 | /// \return Pointer to the list of providers of that \a type, 189 | /// or NULL if \a type is not registered. 190 | /// 191 | /// \see Host::getProviders 192 | /// 193 | //////////////////////////////////////////////////////////// 194 | const std::list* getProviders(const std::string& type) const; 195 | 196 | 197 | private: 198 | 199 | //////////////////////////////////////////////////////////// 200 | /// \brief Get the plugin name (without extension) from its path 201 | /// 202 | /// \param path Plugin path. 203 | /// 204 | /// \return Name of the plugin. 205 | /// 206 | /// \see resolvePathExtension 207 | /// \see load(const std::string&, const std::string&) 208 | /// \see load(const std::string&) 209 | /// \see unload 210 | /// 211 | //////////////////////////////////////////////////////////// 212 | static std::string getPluginName(const std::string& path); 213 | 214 | //////////////////////////////////////////////////////////// 215 | /// \brief If the plugin path omits it's extension, this method returns 216 | /// the path plus the OS specific dll extension. 217 | /// Return a copy of the path otherwise. 218 | /// 219 | /// \param path Plugin path. 220 | /// 221 | /// \return Path with extension. 222 | /// 223 | /// \see getPluginName 224 | /// \see load(const std::string&, const std::string&) 225 | /// \see load(const std::string&) 226 | /// \see unload 227 | /// 228 | //////////////////////////////////////////////////////////// 229 | static std::string resolvePathExtension(const std::string& path); 230 | 231 | 232 | private: 233 | 234 | /// Signature for the plugin's registration function 235 | typedef bool fnRegisterPlugin(Host&); 236 | typedef std::map LibMap; 237 | 238 | LibMap libraries; ///< Map containing the loaded libraries 239 | Host host; ///< Host app proxy, holding all providers 240 | 241 | }; 242 | 243 | } // namespace pluma 244 | 245 | #endif // PLUMA_PLUGIN_MANAGER_HPP 246 | -------------------------------------------------------------------------------- /include/Pluma/Pluma.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_PLUMA_HPP 26 | #define PLUMA_PLUMA_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | #include 34 | 35 | //////////////////////////////////////////////////////////// 36 | // Andy macro to convert parameter to string 37 | //////////////////////////////////////////////////////////// 38 | #define PLUMA_2STRING(X) #X 39 | 40 | //////////////////////////////////////////////////////////// 41 | // Macro that generate first part of the provider definition 42 | //////////////////////////////////////////////////////////// 43 | #define PLUMA_PROVIDER_HEADER_BEGIN(TYPE)\ 44 | class TYPE##Provider: public pluma::Provider{\ 45 | private:\ 46 | friend class pluma::Pluma;\ 47 | static const unsigned int PLUMA_INTERFACE_VERSION;\ 48 | static const unsigned int PLUMA_INTERFACE_LOWEST_VERSION;\ 49 | static const std::string PLUMA_PROVIDER_TYPE;\ 50 | std::string plumaGetType() const{ return PLUMA_PROVIDER_TYPE; }\ 51 | public:\ 52 | unsigned int getVersion() const{ return PLUMA_INTERFACE_VERSION; } 53 | 54 | //////////////////////////////////////////////////////////// 55 | // Macro that generate last part of the provider definition 56 | //////////////////////////////////////////////////////////// 57 | #define PLUMA_PROVIDER_HEADER_END }; 58 | 59 | //////////////////////////////////////////////////////////// 60 | // Macro that generate the provider declaration 61 | //////////////////////////////////////////////////////////// 62 | #define PLUMA_PROVIDER_SOURCE(TYPE, Version, LowestVersion)\ 63 | const std::string TYPE##Provider::PLUMA_PROVIDER_TYPE = PLUMA_2STRING( TYPE );\ 64 | const unsigned int TYPE##Provider::PLUMA_INTERFACE_VERSION = Version;\ 65 | const unsigned int TYPE##Provider::PLUMA_INTERFACE_LOWEST_VERSION = LowestVersion; 66 | 67 | 68 | //////////////////////////////////////////////////////////// 69 | // Macro that helps plugins generating their provider implementations 70 | // PRE: SPECIALIZED_TYPE must inherit from BASE_TYPE 71 | //////////////////////////////////////////////////////////// 72 | #define PLUMA_INHERIT_PROVIDER(SPECIALIZED_TYPE, BASE_TYPE)\ 73 | class SPECIALIZED_TYPE##Provider: public BASE_TYPE##Provider{\ 74 | public:\ 75 | BASE_TYPE * create() const{ return new SPECIALIZED_TYPE (); }\ 76 | }; 77 | 78 | 79 | //////////////////////////////////////////////////////////// 80 | // Macro that helps host applications defining 81 | // their provider classes 82 | //////////////////////////////////////////////////////////// 83 | #define PLUMA_PROVIDER_HEADER(TYPE) \ 84 | PLUMA_PROVIDER_HEADER_BEGIN(TYPE) \ 85 | virtual TYPE* create() const = 0; \ 86 | PLUMA_PROVIDER_HEADER_END 87 | 88 | namespace pluma{ 89 | 90 | //////////////////////////////////////////////////////////// 91 | /// \brief Pluma plugins management 92 | /// 93 | //////////////////////////////////////////////////////////// 94 | class Pluma: public PluginManager{ 95 | 96 | public: 97 | //////////////////////////////////////////////////////////// 98 | /// \brief Default Constructor 99 | /// 100 | //////////////////////////////////////////////////////////// 101 | Pluma(); 102 | 103 | //////////////////////////////////////////////////////////// 104 | /// \brief Tell Pluma to accept a certain type of providers 105 | /// 106 | /// A Pluma object is able to accept multiple types of providers. 107 | /// When a plugin is loaded, it tries to register it's providers 108 | /// implementations. Those are only accepted by the host 109 | /// application if it's accepting providers of that kind. 110 | /// 111 | /// \tparam ProviderType type of provider. 112 | /// 113 | //////////////////////////////////////////////////////////// 114 | template 115 | void acceptProviderType(); 116 | 117 | //////////////////////////////////////////////////////////// 118 | /// \brief Get the stored providers of a certain type. 119 | /// 120 | /// Providers are added at the end of the \a providers vector. 121 | /// 122 | /// \tparam ProviderType type of provider to be returned. 123 | /// \param[out] providers Vector to fill with the existing 124 | /// providers. 125 | /// 126 | //////////////////////////////////////////////////////////// 127 | template 128 | void getProviders(std::vector& providers); 129 | }; 130 | 131 | #include 132 | 133 | } 134 | 135 | 136 | #endif // PLUMA_PLUMA_HPP 137 | 138 | 139 | //////////////////////////////////////////////////////////// 140 | /// \class pluma::Pluma 141 | /// 142 | /// Pluma is the main class of Pluma library. Allows hosting 143 | /// applications to load/unload dlls in runtime (plugins), and 144 | /// to get providers of shared interface objects. 145 | /// 146 | /// Example: 147 | /// \code 148 | /// pluma::Pluma pluma; 149 | /// // Tell it to accept providers of the type DeviceProvider 150 | /// pluma.acceptProviderType(); 151 | /// // Load some dll 152 | /// pluma.load("plugins/standard_devices"); 153 | /// // Get device providers into a vector 154 | /// std::vector providers; 155 | /// pluma.getProviders(providers); 156 | /// // create a Device from the first provider 157 | /// if (!providers.empty()){ 158 | /// Device* myDevice = providers.first()->create(); 159 | /// // do something with myDevice 160 | /// std::cout << device->getDescription() << std::endl; 161 | /// // (...) 162 | /// delete myDevice; 163 | /// } 164 | /// \endcode 165 | /// 166 | /// It is also possible to add local providers, providers that 167 | /// are defined directly on the host application. That can 168 | /// be useful to provide and use default implementations of certain 169 | /// interfaces, along with plugin implementations. 170 | /// 171 | //////////////////////////////////////////////////////////// 172 | -------------------------------------------------------------------------------- /include/Pluma/Pluma.inl: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | inline Pluma::Pluma(){ 28 | // Nothing to do 29 | } 30 | 31 | 32 | //////////////////////////////////////////////////////////// 33 | template 34 | void Pluma::acceptProviderType(){ 35 | PluginManager::registerType( 36 | ProviderType::PLUMA_PROVIDER_TYPE, 37 | ProviderType::PLUMA_INTERFACE_VERSION, 38 | ProviderType::PLUMA_INTERFACE_LOWEST_VERSION 39 | ); 40 | } 41 | 42 | 43 | //////////////////////////////////////////////////////////// 44 | template 45 | void Pluma::getProviders(std::vector& providers){ 46 | const std::list* lst = PluginManager::getProviders(ProviderType::PLUMA_PROVIDER_TYPE); 47 | if (!lst) return; 48 | providers.reserve(providers.size() + lst->size()); 49 | std::list::const_iterator it; 50 | for (it = lst->begin() ; it != lst->end() ; ++it) 51 | providers.push_back(static_cast(*it)); 52 | } 53 | -------------------------------------------------------------------------------- /include/Pluma/PlumaCore.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PLUMACORE_H 2 | #define PLUMACORE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef WIN32 17 | #define __SysWorkDirCmd "chdir" 18 | #elif linux 19 | #define __SysWorkDirCmd "pwd" 20 | #else 21 | #define __SysWorkDirCmd "echo unknown directory execute command!" 22 | #endif 23 | 24 | namespace PlumaCore //Pluma内核 25 | { 26 | 27 | const class _ts_t{ public: inline void tFunc(){} }_classSizeCheck; 28 | const size_t _SysClassPSize = sizeof(&_classSizeCheck); 29 | const size_t _SysClassFSize = sizeof(&_ts_t::tFunc); 30 | 31 | typedef std::array ClassVarient; //类万能转换类 32 | typedef std::array MethodVarient; //方法万能转换类 33 | 34 | /// 35 | /// 任意类型转换成格式化地址 如:std::array 36 | /// 37 | /// 模板T 可以传递任意类型 38 | /// 模板变量T 的形参 此参数必须重载operarot =() 39 | /// 40 | template 41 | static std::array _ConvtAnyBAToFormat(const T elem) //Type has operator=() 42 | { 43 | union Convt_t 44 | { 45 | T Base; 46 | std::array iBase; 47 | }result; 48 | result.Base = elem; 49 | return result.iBase; 50 | } 51 | 52 | template 53 | static T _ConvtAnyFormatToBA(std::array elem) //Type has operator=() 54 | { 55 | union Convt_t 56 | { 57 | T Base; 58 | std::array iBase; 59 | }result; 60 | result.iBase = elem; 61 | return result.Base; 62 | } 63 | 64 | template 65 | class Functor 66 | { 67 | typedef Rt(Ct::*Method_t)(Args...); 68 | std::array _methodBase; 69 | std::array _classBase; 70 | 71 | public: 72 | explicit Functor() 73 | { 74 | 75 | } 76 | 77 | Functor(Ct* clazz, Method_t method) 78 | { 79 | _classBase = PlumaCore::_ConvtAnyBAToFormat(clazz); 80 | _methodBase = PlumaCore::_ConvtAnyBAToFormat(method); 81 | } 82 | 83 | void operator = (Functor& func) 84 | { 85 | this->_methodBase == func.getMethodBase(); 86 | this->_classBase == func.getClassBase(); 87 | } 88 | 89 | void getMethodBase() 90 | { 91 | return _methodBase; 92 | } 93 | 94 | void getClassBase() 95 | { 96 | return _classBase; 97 | } 98 | 99 | Rt call(Args...as) 100 | { 101 | using namespace PlumaCore; 102 | return (_ConvtAnyFormatToBA(_classBase)->*_ConvtAnyFormatToBA(_methodBase))(as...); 103 | } 104 | 105 | }; 106 | 107 | 108 | static std::string replace(std::string src,std::string reg,std::string rep) 109 | { 110 | std::string result; 111 | 112 | while(src.find(reg) > 0 && src.find(reg) < src.size()) 113 | { 114 | size_t fpos = src.find(reg); 115 | src.replace(fpos,reg.size(),rep); 116 | } 117 | return src; 118 | } 119 | 120 | class Application 121 | { 122 | static std::vector _procArguments; 123 | static std::string _procRunPath; 124 | static std::string _procRunDir; 125 | static std::string _procRunName; 126 | static std::map> _argsCalled; 127 | static std::map _argsMapping; 128 | static std::map> _channelCalled; 129 | 130 | public: 131 | explicit Application(int& argc,char* argv[]); 132 | 133 | static std::vector arguments(); 134 | 135 | static std::vector channels(); 136 | 137 | static std::map argumentMapping(); 138 | 139 | static std::string argsValue(std::string _key); 140 | 141 | static std::string runPath(); 142 | 143 | static std::string runDir(); 144 | 145 | static std::string name(); 146 | 147 | static void regArgsCalled(std::string flag,std::function handler); 148 | 149 | static void regChannelCalled(std::string flag,std::function handler); 150 | 151 | static void channelCall(std::string flag); 152 | 153 | static void argsCall(); 154 | }; 155 | 156 | ///////////////////////////////////////////////////////////////////////////////// 157 | // Class:Debug 158 | // 实现功能: 159 | // 1.线程输出的互斥锁 160 | // 2.结尾自动换行 161 | // 3.支持所有std::cout 输出范式 162 | // 4.文件头结尾宏封装 PDebug 163 | // 5.std::vec 和std::list 等容器的基本输出 164 | // 使用方法: 165 | // PDebug() << any; 166 | ///////////////////////////////////////////////////////////////////////////////// 167 | class Debug 168 | { 169 | static Debug *_This; 170 | static std::mutex _mut; 171 | 172 | public: 173 | static Debug& getInstance() 174 | { 175 | std::cout << std::dec << std::endl; 176 | if(_This == nullptr) 177 | { 178 | _This = new Debug(); 179 | } 180 | return *_This; 181 | } 182 | 183 | template 184 | Debug& operator <<(const std::vector& _vec) const 185 | { 186 | bool res = _mut.try_lock(); 187 | int count = _vec.size(); 188 | std::cout << "std::vector("; 189 | for(auto ite: _vec) 190 | { 191 | *this<< ite; 192 | if(count > 1) 193 | { 194 | *this<< ","; 195 | count --; 196 | } 197 | } 198 | std::cout << ")"; 199 | if(res) _mut.unlock(); 200 | return * _This; 201 | } 202 | 203 | template 204 | Debug& operator <<(const std::list& _list) 205 | { 206 | bool res = _mut.try_lock(); 207 | int count = _list.size(); 208 | std::cout << "std::list("; 209 | for(auto ite: _list) 210 | { 211 | *this<< ite; 212 | if(count > 1) 213 | { 214 | *this<< ","; 215 | count --; 216 | } 217 | } 218 | std::cout << ")"; 219 | if(res) _mut.unlock(); 220 | return * _This; 221 | } 222 | 223 | template 224 | Debug& operator <<(const T& t) const 225 | { 226 | bool res = _mut.try_lock(); 227 | std::cout << t; 228 | if(res) _mut.unlock(); 229 | return *_This; 230 | } 231 | 232 | template 233 | Debug& operator <<(const std::map& _map) const 234 | { 235 | bool res = _mut.try_lock(); 236 | std::cout << "std::map("; 237 | int count = _map.size(); 238 | for(auto ite = _map.begin(); ite != _map.end(); ite++) 239 | { 240 | *this << ite->first << ":" << ite->second ; 241 | if(count > 1) 242 | { 243 | *this << "," ; 244 | count --; 245 | } 246 | } 247 | std::cout << ")"; 248 | if(res) _mut.unlock(); 249 | return *_This; 250 | } 251 | 252 | template 253 | Debug& operator <<(const std::multimap& _map) const 254 | { 255 | bool res = _mut.try_lock(); 256 | std::cout << "std::multimap("; 257 | int count = _map.size(); 258 | for(auto ite: _map) 259 | { 260 | *this << ite.first << ":" << ite.second; 261 | if(count > 1) 262 | { 263 | *this << "," ; 264 | count --; 265 | } 266 | } 267 | std::cout << ")"; 268 | if(res) _mut.unlock(); 269 | return *_This; 270 | } 271 | 272 | Debug& operator << (const char* t)const 273 | { 274 | bool res = _mut.try_lock(); 275 | if(std::string(t).size() == 1 276 | && ((0x30 <= t[0] && t[0] <= 0x39) 277 | || (0x41 <= t[0] && t[0] <= 0x5A) 278 | || (0x61 <= t[0] && t[0] <= 0x7A))) //数字 小写字母 大写字母 279 | { 280 | std::cout <<"\"" << t << "\"" << " "; 281 | } 282 | else std::cout << t; 283 | if(res) _mut.unlock(); 284 | return *_This; 285 | } 286 | 287 | Debug& operator << (const std::basic_string t)const 288 | { 289 | bool res = _mut.try_lock(); 290 | std::cout <<"\"" << t << "\""; 291 | if(res) _mut.unlock(); 292 | return *_This; 293 | } 294 | 295 | 296 | private: 297 | explicit Debug(){} 298 | virtual ~Debug(){} 299 | }; 300 | 301 | } 302 | 303 | #define PDebug PlumaCore::Debug::getInstance 304 | 305 | // __FUNCSIG is MSVC definitions print current function name 306 | // __PRETTY_FUNCTION__ is mingw definitions print current function name 307 | #ifdef WIN32 308 | #define FUNCTION_INFO __FUNCSIG__ 309 | #elif linux 310 | #define FUNCTION_INFO __PRETTY_FUNCTION__ 311 | #endif // WIN32|WIN64 312 | 313 | #endif // PLUMACORE_H 314 | -------------------------------------------------------------------------------- /include/Pluma/PlumaPipe.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PLUMAPIPE_H 2 | #define PLUMAPIPE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "PlumaCore.hpp" 11 | 12 | template 13 | class PlumaPipe 14 | { 15 | typedef std::multimap> CallBackMapT; //函数转发列表 16 | CallBackMapT _mapping; 17 | 18 | public: 19 | enum ConnType //size is one 20 | { 21 | Ct_CallBack = 0b00000001, //默认回调 defualt 22 | Ct_ThJoined = 0b00000011, //线程等待 23 | Ct_ThDirect = 0b00000010, //线程分离 24 | Ct_OnlyOne = 0b00000100 //只有绑定一次 25 | }; 26 | 27 | explicit PlumaPipe() //has defualt value 28 | { 29 | 30 | } 31 | 32 | virtual ~PlumaPipe() 33 | { 34 | 35 | } 36 | 37 | template 38 | void connect(Ct* handler,Ft func,ConnType type = Ct_CallBack) 39 | { 40 | 41 | switch (type) 42 | { 43 | case Ct_CallBack: 44 | 45 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 46 | [=](Args...as) 47 | { 48 | (handler->*func)(as...); 49 | } 50 | }); 51 | 52 | break; 53 | 54 | case Ct_ThJoined: 55 | 56 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 57 | [=](Args...as){ 58 | std::thread th(func,handler,as...); 59 | th.join(); 60 | }}); 61 | 62 | break; 63 | 64 | case Ct_ThDirect: 65 | 66 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 67 | [=](Args...as) 68 | { 69 | std::thread th(func,handler,as...); 70 | th.detach(); 71 | } 72 | }); 73 | 74 | break; 75 | 76 | case Ct_OnlyOne: 77 | if(_mapping.find(PlumaCore::_ConvtAnyBAToFormat(func)) != _mapping.end()) 78 | return; 79 | else 80 | { 81 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 82 | [=](Args...as) 83 | { 84 | (handler->*func)(as...); 85 | } 86 | }); 87 | } 88 | break; 89 | 90 | default: 91 | throw "Error, can't connect class method,case connect type is unkonwn"; 92 | break; 93 | } 94 | } 95 | 96 | template 97 | void disconnect(Ct* handler,Ft func) 98 | { 99 | _mapping.erase(PlumaCore::_ConvtAnyBAToFormat(func)); 100 | } 101 | 102 | void send(Args...as) 103 | { 104 | for(auto var:_mapping) 105 | { 106 | (var.second)(as...); 107 | } 108 | } 109 | }; 110 | 111 | #endif // PLUMAPIPE_H 112 | -------------------------------------------------------------------------------- /include/Pluma/Provider.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_PROVIDER_HPP 26 | #define PLUMA_PROVIDER_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | 34 | 35 | namespace pluma{ 36 | class Host; 37 | 38 | //////////////////////////////////////////////////////////// 39 | /// \brief Interface to provide applications with objects from plugins. 40 | /// 41 | //////////////////////////////////////////////////////////// 42 | class PLUMA_API Provider{ 43 | friend class Host; 44 | 45 | 46 | public: 47 | 48 | //////////////////////////////////////////////////////////// 49 | /// \brief Destructor. 50 | /// 51 | //////////////////////////////////////////////////////////// 52 | virtual ~Provider(); 53 | 54 | //////////////////////////////////////////////////////////// 55 | /// \brief Get provider version. 56 | /// 57 | /// \return Version number. 58 | /// 59 | //////////////////////////////////////////////////////////// 60 | virtual unsigned int getVersion() const = 0; 61 | 62 | //////////////////////////////////////////////////////////// 63 | /// \brief Check compatibility with host. 64 | /// 65 | /// The same provider may be compiled with different versions 66 | /// on host side and on plugins side. This function checks if 67 | /// a plugin provider is compatible with the current version of 68 | /// the same provider type on the host side. 69 | /// 70 | /// \param host Host, proxy of host application. 71 | /// 72 | /// \return True if it's compatible with \a host. 73 | /// 74 | //////////////////////////////////////////////////////////// 75 | bool isCompatible(const Host& host) const; 76 | 77 | 78 | private: 79 | 80 | //////////////////////////////////////////////////////////// 81 | /// \brief Get provider type. 82 | /// 83 | /// Each provider defined on the host application is identified by 84 | /// a unique type. Those types are automatically managed internally by 85 | /// pluma. 86 | /// 87 | /// \return Provider type id. 88 | /// 89 | //////////////////////////////////////////////////////////// 90 | virtual std::string plumaGetType() const = 0; 91 | 92 | }; 93 | 94 | } // namespace pluma 95 | 96 | 97 | #endif // PLUMA_PROVIDER_HPP 98 | 99 | 100 | //////////////////////////////////////////////////////////// 101 | /// \class pluma::Provider 102 | /// The plugin specific implementations are unknown at the host side, 103 | /// only their shared interfaces are known. Then, host app needs a generic 104 | /// way of create interface objects. That's what provider classes are for. 105 | /// It is the factory design pattern 106 | /// (http://www.oodesign.com/factory-pattern.html) 107 | /// 108 | /// Shared interfaces define their provider types (by inheriting from 109 | /// pluma::Provider). Hosts then use those tipes to get objects from the 110 | /// plugins. 111 | /// Plugins derive the shared interface providers so that they can provide 112 | /// host with specific implementations of the shared interface. 113 | /// Those specific providers are given to the host through a connect function. 114 | /// 115 | /// 116 | /// Example: A host app uses objects of type Device. A certain plugin 117 | /// defines a Keyboard, witch is a Device. 118 | /// The Host will use DeviceProviders to create objects of type Device. 119 | /// The plugin will provide host specifically with a KeyboardProvider. 120 | /// Other plugins may provide host with other derived DeviceProvider types. 121 | /// 122 | /// Device hpp (shared): 123 | /// \code 124 | /// #include 125 | /// class Device{ 126 | /// public: 127 | /// virtual std::string getDescription() const = 0; 128 | /// }; 129 | /// // create DevicedProvider class 130 | /// PLUMA_PROVIDER_HEADER(Device); 131 | /// \endcode 132 | /// 133 | /// Device cpp (shared): 134 | /// \code 135 | /// #include "Device.hpp" 136 | /// generate DevicedProvider with version 6, and compatible with at least v.3 137 | /// PLUMA_PROVIDER_SOURCE(Device, 6, 3); 138 | /// \endcode 139 | /// 140 | /// 141 | ///
142 | /// Keyboard code on the plugin side: 143 | /// \code 144 | /// #include 145 | /// #include "Device.hpp" 146 | /// 147 | /// class Keyboard: public Device{ 148 | /// public: 149 | /// std::string getDescription() const{ 150 | /// return "keyboard"; 151 | /// } 152 | /// }; 153 | /// 154 | /// // create KeyboardProvider, it implements DeviceProvider 155 | /// PLUMA_INHERIT_PROVIDER(Keyboard, Device); 156 | /// \endcode 157 | /// 158 | /// plugin connector: 159 | /// \code 160 | /// #include 161 | /// #include "Keyboard.hpp" 162 | /// 163 | /// PLUMA_CONNECTOR 164 | /// bool connect(pluma::Host& host){ 165 | /// // add a keyboard provider to host 166 | /// host.add( new KeyboardProvider() ); 167 | /// return true; 168 | /// } 169 | /// \endcode 170 | /// 171 | /// 172 | /// Host application code: 173 | /// \code 174 | /// #include 175 | /// 176 | /// #include "Device.hpp" 177 | /// #include 178 | /// #include 179 | /// 180 | /// int main(){ 181 | /// 182 | /// pluma::Pluma plugins; 183 | /// // Tell plugins manager to accept providers of the type DeviceProvider 184 | /// plugins.acceptProviderType(); 185 | /// // Load library "standard_devices" from folder "plugins" 186 | /// plugins.load("plugins", "standard_devices"); 187 | /// 188 | /// // Get device providers into a vector 189 | /// std::vector providers; 190 | /// plugins.getProviders(providers); 191 | /// 192 | /// // create a Device from the first provider 193 | /// if (!providers.empty()){ 194 | /// Device* myDevice = providers.first()->create(); 195 | /// // do something with myDevice 196 | /// std::cout << device->getDescription() << std::endl; 197 | /// // and delete it in the end 198 | /// delete myDevice; 199 | /// } 200 | /// return 0; 201 | /// } 202 | /// \endcode 203 | /// 204 | //////////////////////////////////////////////////////////// 205 | -------------------------------------------------------------------------------- /src/Pluma/DLibrary.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | // Headers 28 | //////////////////////////////////////////////////////////// 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | namespace pluma{ 35 | 36 | //////////////////////////////////////////////////////////// 37 | DLibrary* DLibrary::load(const std::string& path){ 38 | if ( path.empty() ){ 39 | fprintf(stderr, "Failed to load library: Empty path\n"); 40 | return NULL; 41 | } 42 | void* handle = NULL; 43 | 44 | // load library - OS dependent operation 45 | #ifdef PLUMA_SYS_WINDOWS 46 | handle = ::LoadLibraryA(path.c_str()); 47 | if (!handle){ 48 | fprintf(stderr, "Failed to load library \"%s\".\n", path.c_str()); 49 | return NULL; 50 | } 51 | #else 52 | handle = ::dlopen(path.c_str(), RTLD_NOW); 53 | if (!handle){ 54 | const char* errorString = ::dlerror(); 55 | fprintf(stderr, "Failed to load library \"%s\".", path.c_str()); 56 | if(errorString) fprintf(stderr, " OS returned error: \"%s\".", errorString); 57 | fprintf(stderr, "\n"); 58 | return NULL; 59 | } 60 | #endif 61 | // return a DLibrary with the DLL handle 62 | return new DLibrary(handle); 63 | } 64 | 65 | 66 | //////////////////////////////////////////////////////////// 67 | DLibrary::~DLibrary(){ 68 | if (handle){ 69 | #ifdef PLUMA_SYS_WINDOWS 70 | ::FreeLibrary( (HMODULE)handle ); 71 | #else 72 | ::dlclose(handle); 73 | #endif 74 | } 75 | } 76 | 77 | 78 | //////////////////////////////////////////////////////////// 79 | void* DLibrary::getSymbol(const std::string& symbol){ 80 | if (!handle){ 81 | fprintf(stderr, "Cannot inspect library symbols, library isn't loaded.\n"); 82 | return NULL; 83 | } 84 | void* res; 85 | #ifdef PLUMA_SYS_WINDOWS 86 | res = (void*)(::GetProcAddress((HMODULE)handle, symbol.c_str())); 87 | #else 88 | res = (void*)(::dlsym(handle, symbol.c_str())); 89 | #endif 90 | if (!res){ 91 | fprintf(stderr, "Library symbol \"%s\" not found.\n", symbol.c_str()); 92 | return NULL; 93 | } 94 | return res; 95 | } 96 | 97 | 98 | //////////////////////////////////////////////////////////// 99 | DLibrary::DLibrary(void* handle): 100 | handle(handle) 101 | { 102 | // Nothing to do 103 | } 104 | 105 | } // namespace pluma 106 | 107 | -------------------------------------------------------------------------------- /src/Pluma/DLibrary.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_DYNAMIC_LIBRARY_HPP 26 | #define PLUMA_DYNAMIC_LIBRARY_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | 34 | // include OS dependent support for DLL 35 | #ifdef PLUMA_SYS_WINDOWS 36 | #include 37 | #else 38 | #include 39 | #endif 40 | 41 | 42 | 43 | namespace pluma{ 44 | 45 | //////////////////////////////////////////////////////////// 46 | /// \brief Manages a Dynamic Linking Library. 47 | /// 48 | //////////////////////////////////////////////////////////// 49 | class DLibrary{ 50 | 51 | 52 | public: 53 | 54 | //////////////////////////////////////////////////////////// 55 | /// \brief Load a library. 56 | /// 57 | /// \param path Path to the library. 58 | /// 59 | /// \return Pointer to the loaded library, or NULL if failed. 60 | /// 61 | //////////////////////////////////////////////////////////// 62 | static DLibrary* load(const std::string& path); 63 | 64 | //////////////////////////////////////////////////////////// 65 | /// \brief Destructor. 66 | /// 67 | /// Close and free the opened library (if any). 68 | /// 69 | //////////////////////////////////////////////////////////// 70 | ~DLibrary(); 71 | 72 | //////////////////////////////////////////////////////////// 73 | /// \brief Get a symbol from the library. 74 | /// 75 | /// \param symbol Symbol that we're looking for. 76 | /// 77 | /// \return Pointer to what the symbol refers to, or NULL if 78 | /// the symbol is not found. 79 | /// 80 | //////////////////////////////////////////////////////////// 81 | void* getSymbol(const std::string& symbol); 82 | 83 | 84 | private: 85 | 86 | //////////////////////////////////////////////////////////// 87 | /// \brief Default constructor. 88 | /// 89 | /// Library instances cannot be created, use load instead. 90 | /// 91 | /// \see load 92 | /// 93 | //////////////////////////////////////////////////////////// 94 | DLibrary(); 95 | 96 | //////////////////////////////////////////////////////////// 97 | /// \brief Constructor via library handle. 98 | /// 99 | /// Used on load function. 100 | /// 101 | /// \see load 102 | /// 103 | //////////////////////////////////////////////////////////// 104 | DLibrary(void* handle); 105 | 106 | 107 | 108 | //////////////////////////////////////////////////////////// 109 | // Member data 110 | //////////////////////////////////////////////////////////// 111 | 112 | 113 | private: 114 | 115 | void* handle; ///< Library handle. 116 | 117 | }; 118 | 119 | 120 | } // namespace pluma 121 | 122 | 123 | #endif // PLUMA_DYNAMIC_LIBRARY_HPP 124 | -------------------------------------------------------------------------------- /src/Pluma/Dir.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | // Headers 28 | //////////////////////////////////////////////////////////// 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | namespace pluma{ 36 | 37 | namespace dir{ 38 | 39 | 40 | //////////////////////////////////////////////////////////// 41 | void listFiles(std::list& list, const std::string& folder, const std::string& extension, bool recursive){ 42 | DIR* dir; 43 | DIR* subDir; 44 | struct dirent *ent; 45 | // try to open top folder 46 | dir = opendir(folder.c_str()); 47 | if (dir == NULL){ 48 | // could not open directory 49 | fprintf(stderr, "Could not open \"%s\" directory.\n", folder.c_str()); 50 | return; 51 | }else{ 52 | // close, we'll process it next 53 | closedir(dir); 54 | } 55 | // enqueue top folder 56 | std::queue folders; 57 | folders.push(folder); 58 | 59 | // run while has queued folders 60 | while (!folders.empty()){ 61 | std::string currFolder = folders.front(); 62 | folders.pop(); 63 | dir = opendir(currFolder.c_str()); 64 | if (dir == NULL) continue; 65 | // iterate through all the files and directories 66 | while ((ent = readdir (dir)) != NULL) { 67 | std::string name(ent->d_name); 68 | // ignore "." and ".." directories 69 | if ( name.compare(".") == 0 || name.compare("..") == 0) continue; 70 | // add path to the file name 71 | std::string path = currFolder; 72 | path.append("/"); 73 | path.append(name); 74 | // check if it's a folder by trying to open it 75 | subDir = opendir(path.c_str()); 76 | if (subDir != NULL){ 77 | // it's a folder: close, we can process it later 78 | closedir(subDir); 79 | if (recursive) folders.push(path); 80 | }else{ 81 | // it's a file 82 | if (extension.empty()){ 83 | list.push_back(path); 84 | }else{ 85 | // check file extension 86 | size_t lastDot = name.find_last_of('.'); 87 | std::string ext = name.substr(lastDot+1); 88 | if (ext.compare(extension) == 0){ 89 | // match 90 | list.push_back(path); 91 | } 92 | } // endif (extension test) 93 | } // endif (folder test) 94 | } // endwhile (nextFile) 95 | closedir(dir); 96 | } // endwhile (queued folders) 97 | 98 | } // end listFiles 99 | 100 | 101 | } // namespace dir 102 | 103 | } // namespace pluma 104 | -------------------------------------------------------------------------------- /src/Pluma/Dir.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | #ifndef PLUMA_DIRECTORY_HPP 26 | #define PLUMA_DIRECTORY_HPP 27 | 28 | //////////////////////////////////////////////////////////// 29 | // Headers 30 | //////////////////////////////////////////////////////////// 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | namespace pluma{ 37 | 38 | namespace dir{ 39 | 40 | //////////////////////////////////////////////////////////// 41 | /// \brief List files of a directory. 42 | /// 43 | /// \param list The output files list. 44 | /// \param folder The folder where to search in 45 | /// \param extension A file extension filter, 46 | /// empty extension will match all files. 47 | /// \param recursive If true it will list files in 48 | /// sub directories as well. 49 | /// 50 | //////////////////////////////////////////////////////////// 51 | void listFiles( 52 | std::list& list, 53 | const std::string& folder, 54 | const std::string& extension = "", 55 | bool recursive = false 56 | ); 57 | 58 | 59 | } // namespace dir 60 | 61 | } // namespace pluma 62 | 63 | 64 | #endif // PLUMA_DIRECTORY_HPP 65 | -------------------------------------------------------------------------------- /src/Pluma/Host.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | // Headers 28 | //////////////////////////////////////////////////////////// 29 | #include 30 | #include 31 | 32 | 33 | namespace pluma{ 34 | 35 | //////////////////////////////////////////////////////////// 36 | Host::Host(){ 37 | // Nothing to do 38 | } 39 | 40 | 41 | //////////////////////////////////////////////////////////// 42 | bool Host::add(Provider* provider){ 43 | if (provider == NULL){ 44 | fprintf(stderr, "Trying to add a null provider.\n"); 45 | return false; 46 | } 47 | if (!validateProvider(provider)){ 48 | delete provider; 49 | return false; 50 | } 51 | addRequests[ provider->plumaGetType() ].push_back(provider); 52 | return true; 53 | } 54 | 55 | 56 | //////////////////////////////////////////////////////////// 57 | Host::~Host(){ 58 | clearProviders(); 59 | // map frees itself 60 | } 61 | 62 | 63 | //////////////////////////////////////////////////////////// 64 | void Host::clearProviders(){ 65 | ProvidersMap::iterator it; 66 | for (it = knownTypes.begin() ; it != knownTypes.end() ; ++it){ 67 | std::list& providers = it->second.providers; 68 | std::list::iterator provIt; 69 | for (provIt = providers.begin() ; provIt != providers.end() ; ++provIt){ 70 | delete *provIt; 71 | } 72 | std::list().swap(providers); 73 | } 74 | } 75 | 76 | 77 | //////////////////////////////////////////////////////////// 78 | bool Host::knows(const std::string& type) const{ 79 | return knownTypes.find(type) != knownTypes.end(); 80 | } 81 | 82 | 83 | //////////////////////////////////////////////////////////// 84 | unsigned int Host::getVersion(const std::string& type) const{ 85 | ProvidersMap::const_iterator it = knownTypes.find(type); 86 | if (it != knownTypes.end()) 87 | return it->second.version; 88 | return 0; 89 | } 90 | 91 | 92 | //////////////////////////////////////////////////////////// 93 | unsigned int Host::getLowestVersion(const std::string& type) const{ 94 | ProvidersMap::const_iterator it = knownTypes.find(type); 95 | if (it != knownTypes.end()) 96 | return it->second.lowestVersion; 97 | return 0; 98 | } 99 | 100 | 101 | //////////////////////////////////////////////////////////// 102 | void Host::registerType(const std::string& type, unsigned int version, unsigned int lowestVersion){ 103 | if (!knows(type)){ 104 | ProviderInfo pi; 105 | pi.version = version; 106 | pi.lowestVersion = lowestVersion; 107 | knownTypes[type] = pi; 108 | } 109 | } 110 | 111 | 112 | //////////////////////////////////////////////////////////// 113 | const std::list* Host::getProviders(const std::string& type) const{ 114 | ProvidersMap::const_iterator it = knownTypes.find(type); 115 | if (it != knownTypes.end()) 116 | return &it->second.providers; 117 | return NULL; 118 | } 119 | 120 | 121 | //////////////////////////////////////////////////////////// 122 | bool Host::validateProvider(Provider* provider) const{ 123 | const std::string& type = provider->plumaGetType(); 124 | if ( !knows(type) ){ 125 | fprintf(stderr, "%s provider type isn't registered.\n", type.c_str()); 126 | return false; 127 | } 128 | if (!provider->isCompatible(*this)){ 129 | fprintf(stderr, "Incompatible %s provider version.\n", type.c_str()); 130 | return false; 131 | } 132 | return true; 133 | } 134 | 135 | 136 | //////////////////////////////////////////////////////////// 137 | bool Host::registerProvider(Provider* provider){ 138 | if (!validateProvider(provider)){ 139 | delete provider; 140 | return false; 141 | } 142 | knownTypes[ provider->plumaGetType() ].providers.push_back(provider); 143 | return true; 144 | } 145 | 146 | 147 | //////////////////////////////////////////////////////////// 148 | void Host::cancelAddictions(){ 149 | TempProvidersMap::iterator it; 150 | for( it = addRequests.begin() ; it != addRequests.end() ; ++it){ 151 | std::list lst = it->second; 152 | std::list::iterator providerIt; 153 | for (providerIt = lst.begin() ; providerIt != lst.end() ; ++providerIt){ 154 | delete *providerIt; 155 | } 156 | } 157 | // clear map 158 | TempProvidersMap().swap(addRequests); 159 | } 160 | 161 | 162 | //////////////////////////////////////////////////////////// 163 | bool Host::confirmAddictions(){ 164 | if (addRequests.empty()) return false; 165 | TempProvidersMap::iterator it; 166 | for( it = addRequests.begin() ; it != addRequests.end() ; ++it){ 167 | std::list lst = it->second; 168 | std::list::iterator providerIt; 169 | for (providerIt = lst.begin() ; providerIt != lst.end() ; ++providerIt){ 170 | knownTypes[it->first].providers.push_back(*providerIt); 171 | } 172 | } 173 | // clear map 174 | TempProvidersMap().swap(addRequests); 175 | return true; 176 | } 177 | 178 | 179 | } //namespace pluma 180 | -------------------------------------------------------------------------------- /src/Pluma/PluginManager.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | // Headers 28 | //////////////////////////////////////////////////////////// 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace pluma{ 36 | 37 | //////////////////////////////////////////////////////////// 38 | PluginManager::PluginManager(){ 39 | // Nothing to do 40 | } 41 | 42 | 43 | //////////////////////////////////////////////////////////// 44 | PluginManager::~PluginManager(){ 45 | unloadAll(); 46 | } 47 | 48 | //////////////////////////////////////////////////////////// 49 | bool PluginManager::load(const std::string& path){ 50 | std::string plugName = getPluginName(path); 51 | std::string realPath = resolvePathExtension(path); 52 | DLibrary* lib = DLibrary::load(realPath); 53 | if (!lib) return false; 54 | 55 | fnRegisterPlugin* registerFunction; 56 | registerFunction = reinterpret_cast(lib->getSymbol("connect")); 57 | 58 | if(!registerFunction){ 59 | fprintf(stderr, "Failed to initialize plugin \"%s\": connect function not found\n", plugName.c_str()); 60 | delete lib; 61 | return false; 62 | } 63 | // try to initialize plugin: 64 | if (!registerFunction(host)){ 65 | // plugin decided to fail 66 | fprintf(stderr, "Self registry failed on plugin \"%s\".\n", plugName.c_str()); 67 | host.cancelAddictions(); 68 | delete lib; 69 | return false; 70 | } 71 | // Store the library if addictions are confirmed 72 | if (host.confirmAddictions()) 73 | libraries[plugName] = lib; 74 | else{ 75 | // otherwise nothing was registered 76 | fprintf(stderr, "Nothing registered by plugin \"%s\".\n", plugName.c_str()); 77 | delete lib; 78 | return false; 79 | } 80 | return true; 81 | } 82 | 83 | 84 | //////////////////////////////////////////////////////////// 85 | bool PluginManager::load(const std::string& folder, const std::string& pluginName){ 86 | if (folder.empty()) 87 | return load(pluginName); 88 | else if (folder[folder.size()-1] == '/' || folder[folder.size()-1] == '\\') 89 | return load(folder + pluginName); 90 | return load(folder + '/' + pluginName); 91 | } 92 | 93 | //////////////////////////////////////////////////////////// 94 | int PluginManager::loadFromFolder(const std::string& folder, bool recursive){ 95 | std::list files; 96 | dir::listFiles(files, folder, PLUMA_LIB_EXTENSION, recursive); 97 | // try to load every library 98 | int res = 0; 99 | std::list::const_iterator it; 100 | for (it = files.begin() ; it != files.end() ; ++it){ 101 | if ( load(*it) ) ++res; 102 | } 103 | return res; 104 | } 105 | 106 | 107 | //////////////////////////////////////////////////////////// 108 | bool PluginManager::unload(const std::string& pluginName){ 109 | std::string plugName = getPluginName(pluginName); 110 | LibMap::iterator it = libraries.find(plugName); 111 | if( it != libraries.end() ) { 112 | delete it->second; 113 | libraries.erase(it); 114 | return true; 115 | } 116 | return false; 117 | } 118 | 119 | 120 | //////////////////////////////////////////////////////////// 121 | void PluginManager::unloadAll(){ 122 | 123 | host.clearProviders(); 124 | LibMap::iterator it; 125 | for (it = libraries.begin() ; it != libraries.end() ; ++it){ 126 | delete it->second; 127 | } 128 | libraries.clear(); 129 | } 130 | 131 | 132 | //////////////////////////////////////////////////////////// 133 | std::string PluginManager::getPluginName(const std::string& path){ 134 | size_t lastDash = path.find_last_of("/\\"); 135 | size_t lastDot = path.find_last_of('.'); 136 | if (lastDash == std::string::npos) lastDash = 0; 137 | else ++lastDash; 138 | if (lastDot < lastDash || lastDot == std::string::npos){ 139 | // path without extension 140 | lastDot = path.length(); 141 | } 142 | return path.substr(lastDash, lastDot-lastDash); 143 | } 144 | 145 | 146 | //////////////////////////////////////////////////////////// 147 | std::string PluginManager::resolvePathExtension(const std::string& path){ 148 | size_t lastDash = path.find_last_of("/\\"); 149 | size_t lastDot = path.find_last_of('.'); 150 | if (lastDash == std::string::npos) lastDash = 0; 151 | else ++lastDash; 152 | if (lastDot < lastDash || lastDot == std::string::npos){ 153 | // path without extension, add it 154 | return path + "." + PLUMA_LIB_EXTENSION; 155 | } 156 | return path; 157 | } 158 | 159 | 160 | //////////////////////////////////////////////////////////// 161 | void PluginManager::registerType(const std::string& type, unsigned int version, unsigned int lowestVersion){ 162 | host.registerType(type, version, lowestVersion); 163 | } 164 | 165 | 166 | //////////////////////////////////////////////////////////// 167 | bool PluginManager::addProvider(Provider* provider){ 168 | if (provider == NULL){ 169 | fprintf(stderr, "Trying to add null provider\n"); 170 | return false; 171 | } 172 | return host.registerProvider(provider); 173 | } 174 | 175 | 176 | //////////////////////////////////////////////////////////// 177 | void PluginManager::getLoadedPlugins(std::vector& pluginNames) const{ 178 | pluginNames.reserve(pluginNames.size()+libraries.size()); 179 | LibMap::const_iterator it; 180 | for(it = libraries.begin() ; it != libraries.end() ; ++it){ 181 | pluginNames.push_back(&(it->first)); 182 | } 183 | } 184 | 185 | 186 | //////////////////////////////////////////////////////////// 187 | bool PluginManager::isLoaded(const std::string& pluginName) const{ 188 | return libraries.find(getPluginName(pluginName)) != libraries.end(); 189 | } 190 | 191 | 192 | //////////////////////////////////////////////////////////// 193 | const std::list* PluginManager::getProviders(const std::string& type) const{ 194 | return host.getProviders(type); 195 | } 196 | 197 | 198 | 199 | } // namespace pluma 200 | 201 | -------------------------------------------------------------------------------- /src/Pluma/PlumaCore.cpp: -------------------------------------------------------------------------------- 1 | #include "PlumaCore.hpp" 2 | 3 | std::vector PlumaCore::Application::_procArguments = {}; 4 | std::string PlumaCore::Application::_procRunPath = ""; 5 | std::string PlumaCore::Application::_procRunDir = ""; 6 | std::string PlumaCore::Application::_procRunName = ""; 7 | std::map> PlumaCore::Application::_argsCalled = {}; 8 | std::map> PlumaCore::Application::_channelCalled = {}; 9 | std::map PlumaCore::Application::_argsMapping = {}; 10 | PlumaCore::Debug *PlumaCore::Debug::_This = nullptr; 11 | std::mutex PlumaCore::Debug::_mut; 12 | 13 | PlumaCore::Application::Application(int &argc, char *argv[]) 14 | { 15 | for(int idx = 0; idx < argc; idx++) 16 | { 17 | if(idx == 0) 18 | { 19 | _procRunPath = replace(argv[0],"\\","/"); 20 | size_t pos = _procRunPath.find_last_of("/"); 21 | _procRunName = _procRunPath.substr(pos + 1,_procRunDir.size() - pos); 22 | _procRunDir = _procRunPath.substr(0,pos); 23 | } 24 | else 25 | { 26 | _procArguments.push_back(argv[idx]); 27 | } 28 | } 29 | 30 | auto itera = _procArguments.begin(); 31 | for(;itera < _procArguments.end(); itera ++) 32 | { 33 | if(itera->find("-") == 0) 34 | { 35 | _argsMapping.insert({*itera,*(itera+1)}); 36 | } 37 | } 38 | } 39 | 40 | std::vector PlumaCore::Application::arguments() 41 | { 42 | return _procArguments; 43 | } 44 | 45 | std::vector PlumaCore::Application::channels() 46 | { 47 | std::vector result; 48 | for(auto val: _channelCalled) 49 | { 50 | result.push_back(val.first); 51 | } 52 | return result; 53 | } 54 | 55 | std::map PlumaCore::Application::argumentMapping() 56 | { 57 | return _argsMapping; 58 | } 59 | 60 | std::string PlumaCore::Application::runPath() 61 | { 62 | return _procRunPath; 63 | } 64 | 65 | std::string PlumaCore::Application::runDir() 66 | { 67 | return _procRunDir; 68 | } 69 | 70 | std::string PlumaCore::Application::name() 71 | { 72 | return _procRunName; 73 | } 74 | 75 | void PlumaCore::Application::regArgsCalled(std::string flag, std::function handler) 76 | { 77 | _argsCalled.insert({flag,handler}); 78 | } 79 | 80 | void PlumaCore::Application::regChannelCalled(std::string flag,std::function handler) 81 | { 82 | _channelCalled.insert({flag,handler}); 83 | } 84 | 85 | void PlumaCore::Application::argsCall() 86 | { 87 | for(auto mapV : _argsCalled) 88 | { 89 | auto listItera = _procArguments.begin(); 90 | while(listItera != _procArguments.end()) 91 | { 92 | if(*listItera == mapV.first) 93 | { 94 | try 95 | { 96 | mapV.second(*(listItera+1)); 97 | } 98 | catch (std::exception& err) 99 | { 100 | std::string errString = "arguments called error:" + std::string(err.what()); 101 | throw errString; 102 | } 103 | } 104 | listItera++; 105 | } 106 | } 107 | } 108 | 109 | void PlumaCore::Application::channelCall(std::string flag) 110 | { 111 | auto func = _channelCalled[flag]; 112 | if(func != nullptr) 113 | { 114 | try 115 | { 116 | func(); 117 | } 118 | catch (std::exception err) 119 | { 120 | throw std::string("callback channnel") + FUNCTION_INFO + ":" + err.what(); 121 | } 122 | } 123 | else 124 | { 125 | PDebug() << "not found to call channel(process function)"; 126 | } 127 | 128 | PDebug() << ""; 129 | } 130 | 131 | std::string PlumaCore::Application::argsValue(std::string _key) 132 | { 133 | return _argsMapping[_key]; 134 | } 135 | -------------------------------------------------------------------------------- /src/Pluma/PlumaCore.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUMACORE_H 2 | #define PLUMACORE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace PlumaCore 16 | { 17 | 18 | const class _ts_t{ public: inline void tFunc(){} }_classSizeCheck; 19 | const size_t _SysClassPSize = sizeof(&_classSizeCheck); 20 | const size_t _SysClassFSize = sizeof(&_ts_t::tFunc); 21 | 22 | typedef std::array ClassVarient; 23 | typedef std::array MethodVarient; 24 | 25 | template 26 | static std::array _ConvtAnyBAToFormat(const T elem) //Type has operator=() 27 | { 28 | union Convt_t 29 | { 30 | T Base; 31 | std::array iBase; 32 | }result; 33 | result.Base = elem; 34 | return result.iBase; 35 | } 36 | 37 | template 38 | static T _ConvtAnyFormatToBA(std::array elem) //Type has operator=() 39 | { 40 | union Convt_t 41 | { 42 | T Base; 43 | std::array iBase; 44 | }result; 45 | result.iBase = elem; 46 | return result.Base; 47 | } 48 | 49 | template 50 | class Functor 51 | { 52 | typedef Rt(Ct::*Method_t)(Args...); 53 | std::array _methodBase; 54 | std::array _classBase; 55 | 56 | public: 57 | explicit Functor() 58 | { 59 | 60 | } 61 | 62 | Functor(Ct* clazz, Method_t method) 63 | { 64 | _classBase = PlumaCore::_ConvtAnyBAToFormat(clazz); 65 | _methodBase = PlumaCore::_ConvtAnyBAToFormat(method); 66 | } 67 | 68 | void operator = (Functor& func) 69 | { 70 | this->_methodBase == func.getMethodBase(); 71 | this->_classBase == func.getClassBase(); 72 | } 73 | 74 | void getMethodBase() 75 | { 76 | return _methodBase; 77 | } 78 | 79 | void getClassBase() 80 | { 81 | return _classBase; 82 | } 83 | 84 | Rt call(Args...as) 85 | { 86 | using namespace PlumaCore; 87 | return (_ConvtAnyFormatToBA(_classBase)->*_ConvtAnyFormatToBA(_methodBase))(as...); 88 | } 89 | 90 | }; 91 | 92 | 93 | static std::string replace(std::string src,std::string reg,std::string rep) 94 | { 95 | std::string result; 96 | 97 | while(src.find(reg) > 0 && src.find(reg) < src.size()) 98 | { 99 | size_t fpos = src.find(reg); 100 | src.replace(fpos,reg.size(),rep); 101 | } 102 | return src; 103 | } 104 | 105 | class Application 106 | { 107 | static std::vector _procArguments; 108 | static std::string _procRunPath; 109 | static std::string _procRunDir; 110 | static std::string _procRunName; 111 | static std::map> _argsCalled; 112 | static std::map _argsMapping; 113 | static std::map> _channelCalled; 114 | 115 | public: 116 | explicit Application(int& argc,char* argv[]); 117 | 118 | static std::vector arguments(); 119 | 120 | static std::vector channels(); 121 | 122 | static std::map argumentMapping(); 123 | 124 | static std::string argsValue(std::string _key); 125 | 126 | static std::string runPath(); 127 | 128 | static std::string runDir(); 129 | 130 | static std::string name(); 131 | 132 | static void regArgsCalled(std::string flag,std::function handler); 133 | 134 | static void regChannelCalled(std::string flag,std::function handler); 135 | 136 | static void channelCall(std::string flag); 137 | 138 | static void argsCall(); 139 | }; 140 | 141 | class Debug 142 | { 143 | static Debug *_This; 144 | static std::mutex _mut; 145 | 146 | public: 147 | static Debug& getInstance() 148 | { 149 | std::cout << std::dec << std::endl; 150 | if(_This == nullptr) 151 | { 152 | _This = new Debug(); 153 | } 154 | return *_This; 155 | } 156 | 157 | template 158 | Debug& operator <<(const std::vector& _vec) const 159 | { 160 | bool res = _mut.try_lock(); 161 | int count = _vec.size(); 162 | std::cout << "std::vector("; 163 | for(auto ite: _vec) 164 | { 165 | *this<< ite; 166 | if(count > 1) 167 | { 168 | *this<< ","; 169 | count --; 170 | } 171 | } 172 | std::cout << ")"; 173 | if(res) _mut.unlock(); 174 | return * _This; 175 | } 176 | 177 | template 178 | Debug& operator <<(const std::list& _list) 179 | { 180 | bool res = _mut.try_lock(); 181 | int count = _list.size(); 182 | std::cout << "std::list("; 183 | for(auto ite: _list) 184 | { 185 | *this<< ite; 186 | if(count > 1) 187 | { 188 | *this<< ","; 189 | count --; 190 | } 191 | } 192 | std::cout << ")"; 193 | if(res) _mut.unlock(); 194 | return * _This; 195 | } 196 | 197 | template 198 | Debug& operator <<(const T& t) const 199 | { 200 | bool res = _mut.try_lock(); 201 | std::cout << t; 202 | if(res) _mut.unlock(); 203 | return *_This; 204 | } 205 | 206 | template 207 | Debug& operator <<(const std::map& _map) const 208 | { 209 | bool res = _mut.try_lock(); 210 | std::cout << "std::map("; 211 | int count = _map.size(); 212 | for(auto ite = _map.begin(); ite != _map.end(); ite++) 213 | { 214 | *this << ite->first << ":" << ite->second ; 215 | if(count > 1) 216 | { 217 | *this << "," ; 218 | count --; 219 | } 220 | } 221 | std::cout << ")"; 222 | if(res) _mut.unlock(); 223 | return *_This; 224 | } 225 | 226 | template 227 | Debug& operator <<(const std::multimap& _map) const 228 | { 229 | bool res = _mut.try_lock(); 230 | std::cout << "std::multimap("; 231 | int count = _map.size(); 232 | for(auto ite: _map) 233 | { 234 | *this << ite.first << ":" << ite.second; 235 | if(count > 1) 236 | { 237 | *this << "," ; 238 | count --; 239 | } 240 | } 241 | std::cout << ")"; 242 | if(res) _mut.unlock(); 243 | return *_This; 244 | } 245 | 246 | Debug& operator << (const char* t)const 247 | { 248 | bool res = _mut.try_lock(); 249 | if(std::string(t).size() == 1 250 | && ((0x30 <= t[0] && t[0] <= 0x39) 251 | || (0x41 <= t[0] && t[0] <= 0x5A) 252 | || (0x61 <= t[0] && t[0] <= 0x7A))) //数字 小写字母 大写字母 253 | { 254 | std::cout <<"\"" << t << "\"" << " "; 255 | } 256 | else std::cout << t; 257 | if(res) _mut.unlock(); 258 | return *_This; 259 | } 260 | 261 | Debug& operator << (const std::basic_string t)const 262 | { 263 | bool res = _mut.try_lock(); 264 | std::cout <<"\"" << t << "\""; 265 | if(res) _mut.unlock(); 266 | return *_This; 267 | } 268 | 269 | 270 | private: 271 | explicit Debug(){} 272 | virtual ~Debug(){} 273 | }; 274 | 275 | } 276 | 277 | #define PDebug PlumaCore::Debug::getInstance 278 | 279 | #endif // PLUMACORE_H 280 | -------------------------------------------------------------------------------- /src/Pluma/PlumaPipe.cpp: -------------------------------------------------------------------------------- 1 | #include "PlumaPipe.hpp" 2 | -------------------------------------------------------------------------------- /src/Pluma/PlumaPipe.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUMAPIPE_H 2 | #define PLUMAPIPE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "PlumaCore.h" 12 | 13 | template 14 | class PlumaPipe 15 | { 16 | typedef std::multimap> CallBackMapT; //函数转发列表 17 | CallBackMapT _mapping; 18 | 19 | public: 20 | enum ConnType //size is one 21 | { 22 | Ct_CallBack = 0b00000001, //默认回调 defualt 23 | Ct_ThJoined = 0b00000011, //线程等待 24 | Ct_ThDirect = 0b00000010, //线程分离 25 | Ct_OnlyOne = 0b00000100 //只有绑定一次 26 | }; 27 | 28 | explicit PlumaPipe() //has defualt value 29 | { 30 | 31 | } 32 | 33 | virtual ~PlumaPipe() 34 | { 35 | 36 | } 37 | 38 | template 39 | void connect(Ct* handler,Ft func,ConnType type = Ct_CallBack) 40 | { 41 | 42 | switch (type) 43 | { 44 | case Ct_CallBack: 45 | 46 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 47 | [=](Args...as) 48 | { 49 | (handler->*func)(as...); 50 | } 51 | }); 52 | 53 | break; 54 | 55 | case Ct_ThJoined: 56 | 57 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 58 | [=](Args...as){ 59 | std::thread th(func,handler,as...); 60 | th.join(); 61 | }}); 62 | 63 | break; 64 | 65 | case Ct_ThDirect: 66 | 67 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 68 | [=](Args...as) 69 | { 70 | std::thread th(func,handler,as...); 71 | th.detach(); 72 | } 73 | }); 74 | 75 | break; 76 | 77 | case Ct_OnlyOne: 78 | if(_mapping.find(PlumaCore::_ConvtAnyBAToFormat(func)) != _mapping.end()) 79 | return; 80 | else 81 | { 82 | _mapping.insert({PlumaCore::_ConvtAnyBAToFormat(func), 83 | [=](Args...as) 84 | { 85 | (handler->*func)(as...); 86 | } 87 | }); 88 | } 89 | break; 90 | 91 | default: 92 | throw "Error, can't connect class method,case connect type is unkonwn"; 93 | break; 94 | } 95 | } 96 | 97 | template 98 | void disconnect(Ct* handler,Ft func) 99 | { 100 | _mapping.erase(PlumaCore::_ConvtAnyBAToFormat(func)); 101 | } 102 | 103 | void send(Args...as) 104 | { 105 | for(auto var:_mapping) 106 | { 107 | (var.second)(as...); 108 | } 109 | } 110 | }; 111 | 112 | #endif // PLUMAPIPE_H 113 | -------------------------------------------------------------------------------- /src/Pluma/Provider.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////// 2 | // 3 | // Pluma - Plug-in Management Framework 4 | // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) 5 | // 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose, 10 | // including commercial applications, and to alter it and redistribute it freely, 11 | // subject to the following restrictions: 12 | // 13 | // 1. The origin of this software must not be misrepresented; 14 | // you must not claim that you wrote the original software. 15 | // If you use this software in a product, an acknowledgment 16 | // in the product documentation would be appreciated but is not required. 17 | // 18 | // 2. Altered source versions must be plainly marked as such, 19 | // and must not be misrepresented as being the original software. 20 | // 21 | // 3. This notice may not be removed or altered from any source distribution. 22 | // 23 | //////////////////////////////////////////////////////////// 24 | 25 | 26 | //////////////////////////////////////////////////////////// 27 | // Headers 28 | //////////////////////////////////////////////////////////// 29 | #include 30 | #include 31 | 32 | 33 | namespace pluma{ 34 | 35 | //////////////////////////////////////////////////////////// 36 | Provider::~Provider(){ 37 | // Nothing to do 38 | } 39 | 40 | 41 | //////////////////////////////////////////////////////////// 42 | bool Provider::isCompatible(const Host& host) const{ 43 | // check compatibility with host 44 | const std::string& type = this->plumaGetType(); 45 | if (!host.knows(type)) return false; 46 | unsigned int lowest = host.getLowestVersion(type); 47 | unsigned int current = host.getVersion(type); 48 | unsigned int myVersion = this->getVersion(); 49 | return lowest <= myVersion && myVersion <= current; 50 | } 51 | 52 | } // namespace pluma 53 | -------------------------------------------------------------------------------- /src/Pluma/cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.0) 2 | 3 | project(Pluma) 4 | 5 | set(CMAKE_BUILD_RPATH ${CMAKE_CURRENT_SOURCE_DIR}/build) 6 | message(${CMAKE_BUILD_RPATH}) 7 | 8 | add_definitions( 9 | -DPLUMA_EXPORTS 10 | ) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BUILD_RPATH}/lib_Debug) 13 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BUILD_RPATH}/lib_Release) 14 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BUILD_RPATH}/lib_MinSizeRel) 15 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BUILD_RPATH}/lib_RelInfoDebug) 16 | 17 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BUILD_RPATH}/bin_Debug) 18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BUILD_RPATH}/bin_Release) 19 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BUILD_RPATH}/bin_MinSizeRel) 20 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BUILD_RPATH}/bin_RelInfoDebug) 21 | 22 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BUILD_RPATH}/lib_Debug) 23 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BUILD_RPATH}/lib_Release) 24 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BUILD_RPATH}/lib_MinSizeRel) 25 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BUILD_RPATH}/lib_RelInfoDebug) 26 | 27 | set(SOURCE_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include) 28 | set(SOURCE_CPP ${CMAKE_CURRENT_SOURCE_DIR}/src) 29 | 30 | include_directories( 31 | ${SOURCE_HEAD} 32 | ${SOURCE_HEAD}/Pluma 33 | ${SOURCE_CPP} 34 | ${SOURCE_CPP}/Pluma 35 | ) 36 | 37 | aux_source_directory(${SOURCE_CPP}/Pluma ALL_SRC) 38 | 39 | add_library(Pluma STATIC ${ALL_SRC}) 40 | 41 | subdirs(${CMAKE_CURRENT_SOURCE_DIR}/example) 42 | -------------------------------------------------------------------------------- /src/Pluma/out/build/x64-Debug (默认值)/VSInheritEnvironments.txt: -------------------------------------------------------------------------------- 1 | msvc_x64_x64 -------------------------------------------------------------------------------- /src/Pluma/uce-dirent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uce-dirent.h - operating system independent dirent implementation 3 | * 4 | * Copyright (C) 1998-2002 Toni Ronkko 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * ``Software''), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * 26 | * May 28 1998, Toni Ronkko 27 | * 28 | * $Id: uce-dirent.h,v 1.7 2002/05/13 10:48:35 tr Exp $ 29 | * 30 | * $Log: uce-dirent.h,v $ 31 | * Revision 1.7 2002/05/13 10:48:35 tr 32 | * embedded some source code directly to the header so that no source 33 | * modules need to be included in the MS Visual C project using the 34 | * interface, removed all the dependencies to other headers of the `uce' 35 | * library so that the header can be made public 36 | * 37 | * Revision 1.6 2002/04/12 16:22:04 tr 38 | * Unified Compiling Environment (UCE) replaced `std' library 39 | * 40 | * Revision 1.5 2001/07/20 16:33:40 tr 41 | * moved to `std' library and re-named defines accordingly 42 | * 43 | * Revision 1.4 2001/07/10 16:47:18 tronkko 44 | * revised comments 45 | * 46 | * Revision 1.3 2001/01/11 13:16:43 tr 47 | * using ``uce-machine.h'' for finding out defines such as `FREEBSD' 48 | * 49 | * Revision 1.2 2000/10/08 16:00:41 tr 50 | * copy of FreeBSD man page 51 | * 52 | * Revision 1.1 2000/07/10 05:53:16 tr 53 | * Initial revision 54 | * 55 | * Revision 1.2 1998/07/19 18:29:14 tr 56 | * Added error reporting capabilities and some asserts. 57 | * 58 | * Revision 1.1 1998/07/04 16:27:51 tr 59 | * Initial revision 60 | * 61 | * 62 | * MSVC 1.0 scans automatic dependencies incorrectly when your project 63 | * contains this very header. The problem is that MSVC cannot handle 64 | * include directives inside #if..#endif block those are never entered. 65 | * Since this header ought to compile in many different operating systems, 66 | * there had to be several conditional blocks that are compiled only in 67 | * operating systems for what they were designed for. MSVC 1.0 cannot 68 | * handle inclusion of sys/dir.h in a part that is compiled only in Apollo 69 | * operating system. To fix the problem you need to insert DIR.H into 70 | * SYSINCL.DAT located in MSVC\BIN directory and restart visual C++. 71 | * Consult manuals for more informaton about the problem. 72 | * 73 | * Since many UNIX systems have dirent.h we assume to have one also. 74 | * However, if your UNIX system does not have dirent.h you can download one 75 | * for example at: http://ftp.uni-mannheim.de/ftp/GNU/dirent/dirent.tar.gz. 76 | * You can also see if you have one of dirent.h, direct.h, dir.h, ndir.h, 77 | * sys/dir.h and sys/ndir.h somewhere. Try defining HAVE_DIRENT_H, 78 | * HAVE_DIRECT_H, HAVE_DIR_H, HAVE_NDIR_H, HAVE_SYS_DIR_H and 79 | * HAVE_SYS_NDIR_H according to the files found. 80 | */ 81 | #ifndef DIRENT_H 82 | #define DIRENT_H 83 | #define DIRENT_H_INCLUDED 84 | 85 | /* find out platform */ 86 | #if defined(MSDOS) /* MS-DOS */ 87 | #elif defined(__MSDOS__) /* Turbo C/Borland */ 88 | # define MSDOS 89 | #elif defined(__DOS__) /* Watcom */ 90 | # define MSDOS 91 | #endif 92 | 93 | #if defined(WIN32) /* MS-Windows */ 94 | #elif defined(__NT__) /* Watcom */ 95 | # define WIN32 96 | #elif defined(_WIN32) /* Microsoft */ 97 | # define WIN32 98 | #elif defined(__WIN32__) /* Borland */ 99 | # define WIN32 100 | #endif 101 | 102 | /* 103 | * See what kind of dirent interface we have unless autoconf has already 104 | * determinated that. 105 | */ 106 | #if !defined(HAVE_DIRENT_H) && !defined(HAVE_DIRECT_H) && !defined(HAVE_SYS_DIR_H) && !defined(HAVE_NDIR_H) && !defined(HAVE_SYS_NDIR_H) && !defined(HAVE_DIR_H) 107 | # if defined(_MSC_VER) /* Microsoft C/C++ */ 108 | /* no dirent.h */ 109 | # elif defined(__BORLANDC__) /* Borland C/C++ */ 110 | # define HAVE_DIRENT_H 111 | # define VOID_CLOSEDIR 112 | # elif defined(__TURBOC__) /* Borland Turbo C */ 113 | /* no dirent.h */ 114 | # elif defined(__WATCOMC__) /* Watcom C/C++ */ 115 | # define HAVE_DIRECT_H 116 | # elif defined(__apollo) /* Apollo */ 117 | # define HAVE_SYS_DIR_H 118 | # elif defined(__hpux) /* HP-UX */ 119 | # define HAVE_DIRENT_H 120 | # elif defined(__alpha) || defined(__alpha__) /* Alpha OSF1 */ 121 | # error "not implemented" 122 | # elif defined(__sgi) /* Silicon Graphics */ 123 | # define HAVE_DIRENT_H 124 | # elif defined(sun) || defined(_sun) /* Sun Solaris */ 125 | # define HAVE_DIRENT_H 126 | # elif defined(__FreeBSD__) /* FreeBSD */ 127 | # define HAVE_DIRENT_H 128 | # elif defined(__linux__) /* Linux */ 129 | # define HAVE_DIRENT_H 130 | # elif defined(__GNUC__) /* GNU C/C++ */ 131 | # define HAVE_DIRENT_H 132 | # else 133 | # error "not implemented" 134 | # endif 135 | #endif 136 | 137 | /* include proper interface headers */ 138 | #if defined(HAVE_DIRENT_H) 139 | # include 140 | # ifdef FREEBSD 141 | # define NAMLEN(dp) ((int)((dp)->d_namlen)) 142 | # else 143 | # define NAMLEN(dp) ((int)(strlen((dp)->d_name))) 144 | # endif 145 | 146 | #elif defined(HAVE_NDIR_H) 147 | # include 148 | # define NAMLEN(dp) ((int)((dp)->d_namlen)) 149 | 150 | #elif defined(HAVE_SYS_NDIR_H) 151 | # include 152 | # define NAMLEN(dp) ((int)((dp)->d_namlen)) 153 | 154 | #elif defined(HAVE_DIRECT_H) 155 | # include 156 | # define NAMLEN(dp) ((int)((dp)->d_namlen)) 157 | 158 | #elif defined(HAVE_DIR_H) 159 | # include 160 | # define NAMLEN(dp) ((int)((dp)->d_namlen)) 161 | 162 | #elif defined(HAVE_SYS_DIR_H) 163 | # include 164 | # include 165 | # ifndef dirent 166 | # define dirent direct 167 | # endif 168 | # define NAMLEN(dp) ((int)((dp)->d_namlen)) 169 | 170 | #elif defined(MSDOS) || defined(WIN32) 171 | 172 | /* figure out type of underlaying directory interface to be used */ 173 | # if defined(WIN32) 174 | # define DIRENT_WIN32_INTERFACE 175 | # elif defined(MSDOS) 176 | # define DIRENT_MSDOS_INTERFACE 177 | # else 178 | # error "missing native dirent interface" 179 | # endif 180 | 181 | /*** WIN32 specifics ***/ 182 | # if defined(DIRENT_WIN32_INTERFACE) 183 | # include 184 | # if !defined(DIRENT_MAXNAMLEN) 185 | # define DIRENT_MAXNAMLEN (MAX_PATH) 186 | # endif 187 | 188 | 189 | /*** MS-DOS specifics ***/ 190 | # elif defined(DIRENT_MSDOS_INTERFACE) 191 | # include 192 | 193 | /* Borland defines file length macros in dir.h */ 194 | # if defined(__BORLANDC__) 195 | # include 196 | # if !defined(DIRENT_MAXNAMLEN) 197 | # define DIRENT_MAXNAMLEN ((MAXFILE)+(MAXEXT)) 198 | # endif 199 | # if !defined(_find_t) 200 | # define _find_t find_t 201 | # endif 202 | 203 | /* Turbo C defines ffblk structure in dir.h */ 204 | # elif defined(__TURBOC__) 205 | # include 206 | # if !defined(DIRENT_MAXNAMLEN) 207 | # define DIRENT_MAXNAMLEN ((MAXFILE)+(MAXEXT)) 208 | # endif 209 | # define DIRENT_USE_FFBLK 210 | 211 | /* MSVC */ 212 | # elif defined(_MSC_VER) 213 | # if !defined(DIRENT_MAXNAMLEN) 214 | # define DIRENT_MAXNAMLEN (12) 215 | # endif 216 | 217 | /* Watcom */ 218 | # elif defined(__WATCOMC__) 219 | # if !defined(DIRENT_MAXNAMLEN) 220 | # if defined(__OS2__) || defined(__NT__) 221 | # define DIRENT_MAXNAMLEN (255) 222 | # else 223 | # define DIRENT_MAXNAMLEN (12) 224 | # endif 225 | # endif 226 | 227 | # endif 228 | # endif 229 | 230 | /*** generic MS-DOS and MS-Windows stuff ***/ 231 | # if !defined(NAME_MAX) && defined(DIRENT_MAXNAMLEN) 232 | # define NAME_MAX DIRENT_MAXNAMLEN 233 | # endif 234 | # if NAME_MAX < DIRENT_MAXNAMLEN 235 | # error "assertion failed: NAME_MAX >= DIRENT_MAXNAMLEN" 236 | # endif 237 | 238 | 239 | /* 240 | * Substitute for real dirent structure. Note that `d_name' field is a 241 | * true character array although we have it copied in the implementation 242 | * dependent data. We could save some memory if we had declared `d_name' 243 | * as a pointer refering the name within implementation dependent data. 244 | * We have not done that since some code may rely on sizeof(d_name) to be 245 | * something other than four. Besides, directory entries are typically so 246 | * small that it takes virtually no time to copy them from place to place. 247 | */ 248 | typedef struct dirent { 249 | char d_name[NAME_MAX + 1]; 250 | 251 | /*** Operating system specific part ***/ 252 | # if defined(DIRENT_WIN32_INTERFACE) /*WIN32*/ 253 | WIN32_FIND_DATA data; 254 | # elif defined(DIRENT_MSDOS_INTERFACE) /*MSDOS*/ 255 | # if defined(DIRENT_USE_FFBLK) 256 | struct ffblk data; 257 | # else 258 | struct _find_t data; 259 | # endif 260 | # endif 261 | } dirent; 262 | 263 | /* DIR substitute structure containing directory name. The name is 264 | * essential for the operation of ``rewinndir'' function. */ 265 | typedef struct DIR { 266 | char *dirname; /* directory being scanned */ 267 | dirent current; /* current entry */ 268 | int dirent_filled; /* is current un-processed? */ 269 | 270 | /*** Operating system specific part ***/ 271 | # if defined(DIRENT_WIN32_INTERFACE) 272 | HANDLE search_handle; 273 | # elif defined(DIRENT_MSDOS_INTERFACE) 274 | # endif 275 | } DIR; 276 | 277 | # ifdef __cplusplus 278 | extern "C" { 279 | # endif 280 | 281 | /* supply prototypes for dirent functions */ 282 | static DIR *opendir (const char *dirname); 283 | static struct dirent *readdir (DIR *dirp); 284 | static int closedir (DIR *dirp); 285 | static void rewinddir (DIR *dirp); 286 | 287 | /* 288 | * Implement dirent interface as static functions so that the user does not 289 | * need to change his project in any way to use dirent function. With this 290 | * it is sufficient to include this very header from source modules using 291 | * dirent functions and the functions will be pulled in automatically. 292 | */ 293 | #include 294 | #include 295 | #include 296 | #include 297 | #include 298 | 299 | /* use ffblk instead of _find_t if requested */ 300 | #if defined(DIRENT_USE_FFBLK) 301 | # define _A_ARCH (FA_ARCH) 302 | # define _A_HIDDEN (FA_HIDDEN) 303 | # define _A_NORMAL (0) 304 | # define _A_RDONLY (FA_RDONLY) 305 | # define _A_SUBDIR (FA_DIREC) 306 | # define _A_SYSTEM (FA_SYSTEM) 307 | # define _A_VOLID (FA_LABEL) 308 | # define _dos_findnext(dest) findnext(dest) 309 | # define _dos_findfirst(name,flags,dest) findfirst(name,dest,flags) 310 | #endif 311 | 312 | static int _initdir (DIR *p); 313 | static const char *_getdirname (const struct dirent *dp); 314 | static void _setdirname (struct DIR *dirp); 315 | 316 | /* 317 | * 318 | * open directory stream for reading 319 | * DIR *opendir (const char *dirname); 320 | * 321 | * Open named directory stream for read and return pointer to the 322 | * internal working area that is used for retrieving individual directory 323 | * entries. The internal working area has no fields of your interest. 324 | * 325 | * Returns a pointer to the internal working area or NULL in case the 326 | * directory stream could not be opened. Global `errno' variable will set 327 | * in case of error as follows: 328 | * 329 | * 330 | * [EACESS |Permission denied. 331 | * [EMFILE |Too many open files used by the process. 332 | * [ENFILE |Too many open files in system. 333 | * [ENOENT |Directory does not exist. 334 | * [ENOMEM |Insufficient memory. 335 | * [ENOTDIR |dirname does not refer to directory. This value is not 336 | * reliable on MS-DOS and MS-Windows platforms. Many 337 | * implementations return ENOENT even when the name refers to a 338 | * file.] 339 | *
340 | *
341 | */ 342 | static DIR * 343 | opendir( 344 | const char *dirname) 345 | { 346 | DIR *dirp; 347 | assert (dirname != NULL); 348 | 349 | dirp = (DIR*)malloc (sizeof (struct DIR)); 350 | if (dirp != NULL) { 351 | char *p; 352 | 353 | /* allocate room for directory name */ 354 | dirp->dirname = (char*) malloc (strlen (dirname) + 1 + strlen ("\\*.*")); 355 | if (dirp->dirname == NULL) { 356 | /* failed to duplicate directory name. errno set by malloc() */ 357 | free (dirp); 358 | return NULL; 359 | } 360 | /* Copy directory name while appending directory separator and "*.*". 361 | * Directory separator is not appended if the name already ends with 362 | * drive or directory separator. Directory separator is assumed to be 363 | * '/' or '\' and drive separator is assumed to be ':'. */ 364 | strcpy (dirp->dirname, dirname); 365 | p = strchr (dirp->dirname, '\0'); 366 | if (dirp->dirname < p && 367 | *(p - 1) != '\\' && *(p - 1) != '/' && *(p - 1) != ':') 368 | { 369 | strcpy (p++, "/"); 370 | } 371 | # ifdef DIRENT_WIN32_INTERFACE 372 | strcpy (p, "*"); /*scan files with and without extension in win32*/ 373 | # else 374 | strcpy (p, "*.*"); /*scan files with and without extension in DOS*/ 375 | # endif 376 | 377 | /* open stream */ 378 | if (_initdir (dirp) == 0) { 379 | /* initialization failed */ 380 | free (dirp->dirname); 381 | free (dirp); 382 | return NULL; 383 | } 384 | } 385 | return dirp; 386 | } 387 | 388 | 389 | /* 390 | * 391 | * read a directory entry 392 | * struct dirent *readdir (DIR *dirp); 393 | * 394 | * Read individual directory entry and return pointer to a structure 395 | * containing the name of the entry. Individual directory entries returned 396 | * include normal files, sub-directories, pseudo-directories "." and ".." 397 | * and also volume labels, hidden files and system files in MS-DOS and 398 | * MS-Windows. You might want to use stat(2) function to determinate which 399 | * one are you dealing with. Many dirent implementations already contain 400 | * equivalent information in dirent structure but you cannot depend on 401 | * this. 402 | * 403 | * The dirent structure contains several system dependent fields that 404 | * generally have no interest to you. The only interesting one is char 405 | * d_name[] that is also portable across different systems. The d_name 406 | * field contains the name of the directory entry without leading path. 407 | * While d_name is portable across different systems the actual storage 408 | * capacity of d_name varies from system to system and there is no portable 409 | * way to find out it at compile time as different systems define the 410 | * capacity of d_name with different macros and some systems do not define 411 | * capacity at all (besides actual declaration of the field). If you really 412 | * need to find out storage capacity of d_name then you might want to try 413 | * NAME_MAX macro. The NAME_MAX is defined in POSIX standard althought 414 | * there are many MS-DOS and MS-Windows implementations those do not define 415 | * it. There are also systems that declare d_name as "char d_name[1]" and 416 | * then allocate suitable amount of memory at run-time. Thanks to Alain 417 | * Decamps (Alain.Decamps@advalvas.be) for pointing it out to me. 418 | * 419 | * This all leads to the fact that it is difficult to allocate space 420 | * for the directory names when the very same program is being compiled on 421 | * number of operating systems. Therefore I suggest that you always 422 | * allocate space for directory names dynamically. 423 | * 424 | * 425 | * Returns a pointer to a structure containing name of the directory entry 426 | * in `d_name' field or NULL if there was an error. In case of an error the 427 | * global `errno' variable will set as follows: 428 | * 429 | * 430 | * [EBADF |dir parameter refers to an invalid directory stream. This value 431 | * is not set reliably on all implementations.] 432 | *
433 | *
434 | */ 435 | static struct dirent * 436 | readdir (DIR *dirp) 437 | { 438 | assert (dirp != NULL); 439 | if (dirp == NULL) { 440 | errno = EBADF; 441 | return NULL; 442 | } 443 | 444 | #if defined(DIRENT_WIN32_INTERFACE) 445 | if (dirp->search_handle == INVALID_HANDLE_VALUE) { 446 | /* directory stream was opened/rewound incorrectly or it ended normally */ 447 | errno = EBADF; 448 | return NULL; 449 | } 450 | #endif 451 | 452 | if (dirp->dirent_filled != 0) { 453 | /* 454 | * Directory entry has already been retrieved and there is no need to 455 | * retrieve a new one. Directory entry will be retrieved in advance 456 | * when the user calls readdir function for the first time. This is so 457 | * because real dirent has separate functions for opening and reading 458 | * the stream whereas Win32 and DOS dirents open the stream 459 | * automatically when we retrieve the first file. Therefore, we have to 460 | * save the first file when opening the stream and later we have to 461 | * return the saved entry when the user tries to read the first entry. 462 | */ 463 | dirp->dirent_filled = 0; 464 | } else { 465 | /* fill in entry and return that */ 466 | #if defined(DIRENT_WIN32_INTERFACE) 467 | if (FindNextFile (dirp->search_handle, &dirp->current.data) == FALSE) { 468 | /* Last file has been processed or an error occured */ 469 | FindClose (dirp->search_handle); 470 | dirp->search_handle = INVALID_HANDLE_VALUE; 471 | errno = ENOENT; 472 | return NULL; 473 | } 474 | 475 | # elif defined(DIRENT_MSDOS_INTERFACE) 476 | if (_dos_findnext (&dirp->current.data) != 0) { 477 | /* _dos_findnext and findnext will set errno to ENOENT when no 478 | * more entries could be retrieved. */ 479 | return NULL; 480 | } 481 | # endif 482 | 483 | _setdirname (dirp); 484 | assert (dirp->dirent_filled == 0); 485 | } 486 | return &dirp->current; 487 | } 488 | 489 | 490 | /* 491 | * 492 | * close directory stream. 493 | * int closedir (DIR *dirp); 494 | * 495 | * Close directory stream opened by the `opendir' function. Close of 496 | * directory stream invalidates the DIR structure as well as previously read 497 | * dirent entry. 498 | * 499 | * The function typically returns 0 on success and -1 on failure but 500 | * the function may be declared to return void on same systems. At least 501 | * Borland C/C++ and some UNIX implementations use void as a return type. 502 | * The dirent wrapper tries to define VOID_CLOSEDIR whenever closedir is 503 | * known to return nothing. The very same definition is made by the GNU 504 | * autoconf if you happen to use it. 505 | * 506 | * The global `errno' variable will set to EBADF in case of error. 507 | * 508 | */ 509 | static int 510 | closedir (DIR *dirp) 511 | { 512 | int retcode = 0; 513 | 514 | /* make sure that dirp points to legal structure */ 515 | assert (dirp != NULL); 516 | if (dirp == NULL) { 517 | errno = EBADF; 518 | return -1; 519 | } 520 | 521 | /* free directory name and search handles */ 522 | if (dirp->dirname != NULL) free (dirp->dirname); 523 | 524 | #if defined(DIRENT_WIN32_INTERFACE) 525 | if (dirp->search_handle != INVALID_HANDLE_VALUE) { 526 | if (FindClose (dirp->search_handle) == FALSE) { 527 | /* Unknown error */ 528 | retcode = -1; 529 | errno = EBADF; 530 | } 531 | } 532 | #endif 533 | 534 | /* clear dirp structure to make sure that it cannot be used anymore*/ 535 | memset (dirp, 0, sizeof (*dirp)); 536 | # if defined(DIRENT_WIN32_INTERFACE) 537 | dirp->search_handle = INVALID_HANDLE_VALUE; 538 | # endif 539 | 540 | free (dirp); 541 | return retcode; 542 | } 543 | 544 | 545 | /* 546 | * 547 | * rewind directory stream to the beginning 548 | * void rewinddir (DIR *dirp); 549 | * 550 | * Rewind directory stream to the beginning so that the next call of 551 | * readdir() returns the very first directory entry again. However, note 552 | * that next call of readdir() may not return the same directory entry as it 553 | * did in first time. The directory stream may have been affected by newly 554 | * created files. 555 | * 556 | * Almost every dirent implementation ensure that rewinddir will update 557 | * the directory stream to reflect any changes made to the directory entries 558 | * since the previous ``opendir'' or ``rewinddir'' call. Keep an eye on 559 | * this if your program depends on the feature. I know at least one dirent 560 | * implementation where you are required to close and re-open the stream to 561 | * see the changes. 562 | * 563 | * Returns nothing. If something went wrong while rewinding, you will 564 | * notice it later when you try to retrieve the first directory entry. 565 | */ 566 | static void 567 | rewinddir (DIR *dirp) 568 | { 569 | /* make sure that dirp is legal */ 570 | assert (dirp != NULL); 571 | if (dirp == NULL) { 572 | errno = EBADF; 573 | return; 574 | } 575 | assert (dirp->dirname != NULL); 576 | 577 | /* close previous stream */ 578 | #if defined(DIRENT_WIN32_INTERFACE) 579 | if (dirp->search_handle != INVALID_HANDLE_VALUE) { 580 | if (FindClose (dirp->search_handle) == FALSE) { 581 | /* Unknown error */ 582 | errno = EBADF; 583 | } 584 | } 585 | #endif 586 | 587 | /* re-open previous stream */ 588 | if (_initdir (dirp) == 0) { 589 | /* initialization failed but we cannot deal with error. User will notice 590 | * error later when she tries to retrieve first directory enty. */ 591 | /*EMPTY*/; 592 | } 593 | } 594 | 595 | 596 | /* 597 | * Open native directory stream object and retrieve first file. 598 | * Be sure to close previous stream before opening new one. 599 | */ 600 | static int 601 | _initdir (DIR *dirp) 602 | { 603 | assert (dirp != NULL); 604 | assert (dirp->dirname != NULL); 605 | dirp->dirent_filled = 0; 606 | 607 | # if defined(DIRENT_WIN32_INTERFACE) 608 | /* Open stream and retrieve first file */ 609 | dirp->search_handle = FindFirstFile (dirp->dirname, &dirp->current.data); 610 | if (dirp->search_handle == INVALID_HANDLE_VALUE) { 611 | /* something went wrong but we don't know what. GetLastError() could 612 | * give us more information about the error, but then we should map 613 | * the error code into errno. */ 614 | errno = ENOENT; 615 | return 0; 616 | } 617 | 618 | # elif defined(DIRENT_MSDOS_INTERFACE) 619 | if (_dos_findfirst (dirp->dirname, 620 | _A_SUBDIR | _A_RDONLY | _A_ARCH | _A_SYSTEM | _A_HIDDEN, 621 | &dirp->current.data) != 0) 622 | { 623 | /* _dos_findfirst and findfirst will set errno to ENOENT when no 624 | * more entries could be retrieved. */ 625 | return 0; 626 | } 627 | # endif 628 | 629 | /* initialize DIR and it's first entry */ 630 | _setdirname (dirp); 631 | dirp->dirent_filled = 1; 632 | return 1; 633 | } 634 | 635 | 636 | /* 637 | * Return implementation dependent name of the current directory entry. 638 | */ 639 | static const char * 640 | _getdirname (const struct dirent *dp) 641 | { 642 | #if defined(DIRENT_WIN32_INTERFACE) 643 | return dp->data.cFileName; 644 | 645 | #elif defined(DIRENT_USE_FFBLK) 646 | return dp->data.ff_name; 647 | 648 | #else 649 | return dp->data.name; 650 | #endif 651 | } 652 | 653 | 654 | /* 655 | * Copy name of implementation dependent directory entry to the d_name field. 656 | */ 657 | static void 658 | _setdirname (struct DIR *dirp) { 659 | /* make sure that d_name is long enough */ 660 | assert (strlen (_getdirname (&dirp->current)) <= NAME_MAX); 661 | 662 | strncpy (dirp->current.d_name, 663 | _getdirname (&dirp->current), 664 | NAME_MAX); 665 | dirp->current.d_name[NAME_MAX] = '\0'; /*char d_name[NAME_MAX+1]*/ 666 | } 667 | 668 | # ifdef __cplusplus 669 | } 670 | # endif 671 | # define NAMLEN(dp) ((int)(strlen((dp)->d_name))) 672 | 673 | #else 674 | # error "missing dirent interface" 675 | #endif 676 | 677 | 678 | #endif /*DIRENT_H*/ 679 | 680 | --------------------------------------------------------------------------------