diff options
author | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 |
commit | 15740faf9fe9fe4be08965098bbf2947e096aeeb (patch) | |
tree | a730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Modules |
Diffstat (limited to 'Runtime/Modules')
-rw-r--r-- | Runtime/Modules/ExportModules.h | 32 | ||||
-rw-r--r-- | Runtime/Modules/LoadDylib.cpp | 230 | ||||
-rw-r--r-- | Runtime/Modules/LoadDylib.h | 13 | ||||
-rw-r--r-- | Runtime/Modules/ModuleRegistration.cpp | 93 | ||||
-rw-r--r-- | Runtime/Modules/ModuleRegistration.h | 21 | ||||
-rw-r--r-- | Runtime/Modules/RegisterStaticallyLinkedModules.cpp | 73 | ||||
-rw-r--r-- | Runtime/Modules/RegisterStaticallyLinkedModules.h | 3 |
7 files changed, 465 insertions, 0 deletions
diff --git a/Runtime/Modules/ExportModules.h b/Runtime/Modules/ExportModules.h new file mode 100644 index 0000000..47f6b02 --- /dev/null +++ b/Runtime/Modules/ExportModules.h @@ -0,0 +1,32 @@ +#pragma once + +#ifndef BUILDING_COREMODULE +#define BUILDING_COREMODULE 1 +#endif + +#if UNITY_WIN && UNITY_STANDALONE && !UNITY_WINRT && 0 + +#if BUILDING_COREMODULE +#define EXPORT_COREMODULE __declspec(dllexport) +#else +#define EXPORT_COREMODULE __declspec(dllimport) +#endif + +#define EXPORT_MODULE __declspec(dllexport) + +#elif UNITY_OSX && UNITY_STANDALONE && 0 + +#if BUILDING_COREMODULE +#define EXPORT_COREMODULE __attribute__((visibility("default"))) +#else +#define EXPORT_COREMODULE +#endif + +#define EXPORT_MODULE __attribute__((visibility("default"))) + +#else + +#define EXPORT_COREMODULE +#define EXPORT_MODULE + +#endif diff --git a/Runtime/Modules/LoadDylib.cpp b/Runtime/Modules/LoadDylib.cpp new file mode 100644 index 0000000..581a770 --- /dev/null +++ b/Runtime/Modules/LoadDylib.cpp @@ -0,0 +1,230 @@ +#include "UnityPrefix.h" +#include "LoadDylib.h" +#include <map> + +#if UNITY_OSX || UNITY_LINUX +#include "dlfcn.h" +#endif + +#if UNITY_WIN +#include "PlatformDependent/Win/PathUnicodeConversion.h" +#endif + +#if UNITY_WINRT +#include "PlatformDependent/MetroPlayer/MetroUtils.h" +#endif + +using namespace std; + +map<string, void*> gLoaded; + + +std::string GetPathWithPlatformSpecificDllExtension(const std::string& path) +{ + string extended = path; + + #if UNITY_OSX + extended += ".dylib"; + #elif UNITY_WIN + extended += ".dll"; + #elif UNITY_LINUX + extended += ".so"; + #else + ErrorString ("Dynamic module loading not implemented"); + #endif + + return extended; +} + + +void* LoadDynamicLibrary (const std::string& absolutePath) +{ + void* library = NULL; + + // load library if needed + if (gLoaded.find(absolutePath) != gLoaded.end()) + { + library = gLoaded[absolutePath]; + } + else + { + #if UNITY_OSX || UNITY_LINUX + /// RTLD_LOCAL is supposedly default and also completely fails on 10.3.9 + library = dlopen (absolutePath.c_str (), RTLD_NOW); + if ( !library ) + ErrorStringMsg( "ERROR: LoadDynamicLibrary(): %s\n", dlerror() ); + + #elif UNITY_WIN + + #if UNITY_WINRT + HMODULE module = LoadPackagedLibrary (ConvertToWindowsPath(absolutePath.c_str())->Data(), 0); + #else + std::wstring widePath; + ConvertUnityPathName( absolutePath, widePath ); + HINSTANCE module = LoadLibraryW( widePath.c_str() ); + #endif + library = module; + + #endif + + if (library) + { + gLoaded[absolutePath] = library; + } + } + + return library; +} + + +void* LoadAndLookupSymbol (const std::string& absolutePath, const std::string& name) +{ + void* library = LoadDynamicLibrary(absolutePath); + void* symbol = LookupSymbol(library, name); + return symbol; +} + + +void UnloadDynamicLibrary (void* libraryReference) +{ + map<string, void*>::iterator it; + for (it = gLoaded.begin(); it != gLoaded.end(); ++it) + { + if (it->second == libraryReference) + { + #if UNITY_OSX || UNITY_LINUX + dlclose (it->second); + #elif UNITY_WIN + FreeLibrary( (HMODULE)it->second ); + #endif + + gLoaded.erase(it); + break; + } + } +} + + +void UnloadDynamicLibrary (const std::string& absolutePath) +{ + if (gLoaded.count (absolutePath) && gLoaded[absolutePath]) + { + #if UNITY_OSX || UNITY_LINUX + dlclose (gLoaded[absolutePath]); + #elif UNITY_WIN + FreeLibrary( (HMODULE)gLoaded[absolutePath] ); + #endif + } + gLoaded.erase (absolutePath); +} + + +bool LoadAndLookupSymbols (const char* path, ...) +{ + va_list ap; + va_start (ap, path); + while (true) + { + const char* symbolName = va_arg (ap, const char*); + if (symbolName == NULL) + return true; + + void** functionHandle = va_arg (ap, void**); + AssertIf(functionHandle == NULL); + + *functionHandle = LoadAndLookupSymbol (path, symbolName); + if (*functionHandle == NULL) + return false; + } + + return false; +} + +void* LookupSymbol(void* libraryReference, const std::string& symbolName) +{ +#if UNITY_OSX || UNITY_LINUX + + void *sym = dlsym (libraryReference, symbolName.c_str ()); + if (!sym) + ErrorStringMsg("Could not load symbol %s : %s\n", symbolName.c_str(), dlerror()); + return sym; + +#elif UNITY_WIN + + if( !libraryReference ) + return NULL; + return GetProcAddress( (HMODULE)libraryReference, symbolName.c_str() ); + +#else + ErrorStringMsg("LoadAndLookupSymbol is not supported on this platform.\n"); + return NULL; +#endif +} + +/* + +#include <Carbon/Carbon.h> +#import <mach-o/dyld.h> +#import <stdlib.h> +#import <string.h> +#include "FileUtilities.h" + +using namespace std; + +CFBundleRef LoadDynamicLibrary (const string& absolutePath) +{ + CFStringRef cfstring = CFStringCreateWithCString (NULL, ResolveSymlinks(absolutePath).c_str (), kCFStringEncodingUTF8); + + CFURLRef url = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault, + cfstring, + kCFURLPOSIXPathStyle, + false); +// CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8*)absolutePath.c_str (), absolutePath.size (), false); + + CFBundleRef bundle = CFBundleCreate (NULL, url); + CFRelease (url); + CFRelease (cfstring); + if (!bundle) + return false; + + // Check if already loaded + if (CFBundleIsExecutableLoaded (bundle)) + return bundle; + + // Load the bundle + if (!CFBundleLoadExecutable (bundle)) + return NULL; + + return bundle; +} + +void UnloadDynamicLibrary (const string& absolutePath) +{ +// CFURLRef url = CFURLCreateFromFileSystemRepresentation (kCFAllocatorDefault, (const UInt8*)absolutePath.c_str (), absolutePath.size (), false); + CFStringRef cfstring = CFStringCreateWithCString (kCFAllocatorDefault, absolutePath.c_str (), kCFStringEncodingUTF8); + + CFURLRef url = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault, + cfstring, + kCFURLPOSIXPathStyle, + true); + + CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); + CFRelease (cfstring); + if (!bundle) + return; + + CFBundleUnloadExecutable (bundle); +} + +void* LoadAndLookupSymbol (const std::string& absolutePath, const std::string& name) +{ + CFBundleRef bundle = LoadDynamicLibrary (absolutePath); + CFStringRef cfstring = CFStringCreateWithCString (kCFAllocatorDefault, name.c_str (), kCFStringEncodingUTF8); + if (bundle == NULL) + return NULL; + + return CFBundleGetFunctionPointerForName(bundle, cfstring); +}*/ diff --git a/Runtime/Modules/LoadDylib.h b/Runtime/Modules/LoadDylib.h new file mode 100644 index 0000000..7e019d6 --- /dev/null +++ b/Runtime/Modules/LoadDylib.h @@ -0,0 +1,13 @@ +#ifndef LOADDYLIB_H +#define LOADDYLIB_H +#include <string> + +std::string GetPathWithPlatformSpecificDllExtension(const std::string& path); +void* LoadDynamicLibrary (const std::string& absolutePath); +void* LoadAndLookupSymbol (const std::string& absolutePath, const std::string& name); +void UnloadDynamicLibrary (void* libraryReference); +void UnloadDynamicLibrary (const std::string& absolutePath); +bool LoadAndLookupSymbols (const char* path, ...); +void* LookupSymbol(void* libraryReference, const std::string& symbolName); + +#endif diff --git a/Runtime/Modules/ModuleRegistration.cpp b/Runtime/Modules/ModuleRegistration.cpp new file mode 100644 index 0000000..960ae96 --- /dev/null +++ b/Runtime/Modules/ModuleRegistration.cpp @@ -0,0 +1,93 @@ +#include "UnityPrefix.h" +#include "ModuleRegistration.h" +#include "LoadDylib.h" +#include "RegisterStaticallyLinkedModules.h" +#include "Runtime/Utilities/FileUtilities.h" +#include "Runtime/Utilities/PathNameUtility.h" + +#if UNITY_WINRT +#include "PlatformDependent/MetroPlayer/MetroUtils.h" +#endif + +enum { kMaxModuleCount = 10 }; + +static int gAvailableModuleCount = 0; +static ModuleRegistrationInfo gModuleRegistrationInfos[kMaxModuleCount]; + +void RegisterAllAvailableModuleClasses (ClassRegistrationContext& context) +{ + RegisterAvailableModules (); + + for(int i=0;i<gAvailableModuleCount;i++) + { + if (gModuleRegistrationInfos[i].registerClassesCallback != NULL) + gModuleRegistrationInfos[i].registerClassesCallback (context); + } +} + +void RegisterAllAvailableModuleICalls () +{ + RegisterAvailableModules (); + + for(int i=0;i<gAvailableModuleCount;i++) + { + if (gModuleRegistrationInfos[i].registerIcallsCallback != NULL) + gModuleRegistrationInfos[i].registerIcallsCallback (); + } +} + +void RegisterModuleInfo(ModuleRegistrationInfo& info) +{ + gModuleRegistrationInfos[gAvailableModuleCount] = info; + gAvailableModuleCount++; + + // Bump up kMaxModuleCount if we have too many modules. + Assert(gAvailableModuleCount < kMaxModuleCount); +} + +#if !UNITY_WP8 + +void RegisterModuleInDynamicLibrary (const char* dllName, const char* modulename) +{ + std::string dllFullName = dllName; +#if WEBPLUG + ErrorString ("Dynamic module loading not implemented for web plug"); +#elif UNITY_OSX + dllFullName = AppendPathName (GetApplicationPath (), "Contents/Frameworks/MacStandalonePlayer_"+dllFullName+".dylib"); +#elif UNITY_WIN + dllFullName = "StandalonePlayer_"+dllFullName+".dll"; +#elif UNITY_LINUX + dllFullName += "LinuxStandalonePlayer_"+dllFullName+".so"; +#endif + + std::string funcName("RegisterModule_"); + funcName.append(modulename); + void (*registerModuleFunction)() = (void(*)())LoadAndLookupSymbol(dllFullName, funcName); + if (registerModuleFunction == NULL) + return; + + registerModuleFunction(); +} + +#endif + +static void RegisterDynamicallyLinkedModules() +{ + //Work in progress: +// RegisterModuleInDynamicLibrary("GfxDeviceModule_Dynamic","GfxDevice"); +// RegisterModuleInDynamicLibrary("TerrainModule_Dynamic","Terrain"); +// RegisterModuleInDynamicLibrary("NavMeshModule_Dynamic","Navigation"); +// RegisterModuleInDynamicLibrary("AnimationModule_Dynamic","Animation"); +// RegisterModuleInDynamicLibrary("Dynamics2DModule_Dynamic","Physics2D"); +// RegisterModuleInDynamicLibrary("PhysicsModule_Dynamic","Physics"); +// RegisterModuleInDynamicLibrary("PhysicsEditorModule_Dynamic","PhysicsEditor"); +} + +void RegisterAvailableModules () +{ + if (gAvailableModuleCount != 0) + return; + + RegisterStaticallyLinkedModules(); + RegisterDynamicallyLinkedModules(); +} diff --git a/Runtime/Modules/ModuleRegistration.h b/Runtime/Modules/ModuleRegistration.h new file mode 100644 index 0000000..8493f79 --- /dev/null +++ b/Runtime/Modules/ModuleRegistration.h @@ -0,0 +1,21 @@ +#pragma once + +/// Modules are not guaranteed to exist. You must always check if the module getter function returns non-null. + +struct ClassRegistrationContext; + + +void RegisterAllAvailableModuleClasses (ClassRegistrationContext& context); +void RegisterAllAvailableModuleICalls (); +void RegisterAvailableModules (); + +typedef void RegisterClassesCallback (ClassRegistrationContext& context); +typedef void RegisterIcallsCallback (); + +struct ModuleRegistrationInfo +{ + RegisterClassesCallback* registerClassesCallback; + RegisterIcallsCallback* registerIcallsCallback; +}; + +EXPORT_COREMODULE void RegisterModuleInfo(ModuleRegistrationInfo& info);
\ No newline at end of file diff --git a/Runtime/Modules/RegisterStaticallyLinkedModules.cpp b/Runtime/Modules/RegisterStaticallyLinkedModules.cpp new file mode 100644 index 0000000..8a1c284 --- /dev/null +++ b/Runtime/Modules/RegisterStaticallyLinkedModules.cpp @@ -0,0 +1,73 @@ +#include "UnityPrefix.h" + +extern "C" void RegisterModule_Navigation(); +extern "C" void RegisterModule_Physics2D(); +extern "C" void RegisterModule_Physics(); +extern "C" void RegisterModule_PhysicsEditor(); +extern "C" void RegisterModule_Terrain(); +extern "C" void RegisterModule_Audio(); +extern "C" void RegisterModule_Animation(); +extern "C" void RegisterModule_ClusterRenderer(); + +//we diverge from our usual convention that all defines have to be set to either 0 or 1. +//Jam will set the *_IS_DYNAMICALLY_LINKED defines on this single cpp file only, based on if +//jam is planning to link a certain module statically or dynamically. by doing the define check +//with ifndef like this, it avoids having to add all these defines to all targets that do not yet +//support modularization. this method also creates support for having some modules statically linked +//and some modules dynamically, which is incredibly helpful during development of the modularization + +void RegisterStaticallyLinkedModules() +{ +#ifndef NAVMESH_IS_DYNAMICALLY_LINKED + #if !UNITY_WEBGL + RegisterModule_Navigation(); + #endif +#endif + +#ifndef ANIMATION_IS_DYNAMICALLY_LINKED + RegisterModule_Animation(); +#endif + +#ifndef PHYSICS_IS_DYNAMICALLY_LINKED + #if ENABLE_PHYSICS + RegisterModule_Physics(); + #endif +#endif + +#ifndef TERRAIN_IS_DYNAMICALLY_LINKED + #if ENABLE_TERRAIN + RegisterModule_Terrain(); + #endif +#endif + +#ifndef DYNAMICS2D_IS_DYNAMICALLY_LINKED + #if ENABLE_2D_PHYSICS + RegisterModule_Physics2D(); + #endif +#endif + +#ifndef AUDIO_IS_DYNAMICALLY_LINKED + #if ENABLE_AUDIO + RegisterModule_Audio(); + #endif +#endif + +#ifndef CLUSTER_SYNC_IS_DYNAMICALLY_LINKED + #if ENABLE_CLUSTER_SYNC + RegisterModule_ClusterRenderer(); + #endif +#endif + +#if UNITY_EDITOR +#ifndef PHYSICSEDITOR_IS_DYNAMICALLY_LINKED + RegisterModule_PhysicsEditor(); +#endif +#endif + +#if ENABLE_CLUSTER_SYNC +#ifndef CLUSTERRENDERER_IS_DYNAMICALLY_LINKED + RegisterModule_ClusterRenderer(); +#endif +#endif + +}
\ No newline at end of file diff --git a/Runtime/Modules/RegisterStaticallyLinkedModules.h b/Runtime/Modules/RegisterStaticallyLinkedModules.h new file mode 100644 index 0000000..9445630 --- /dev/null +++ b/Runtime/Modules/RegisterStaticallyLinkedModules.h @@ -0,0 +1,3 @@ +#pragma once + +void RegisterStaticallyLinkedModules(); |