summaryrefslogtreecommitdiffstats
path: root/source/core/slang-platform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/slang-platform.cpp')
-rw-r--r--source/core/slang-platform.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/source/core/slang-platform.cpp b/source/core/slang-platform.cpp
new file mode 100644
index 000000000..1cb2bc56e
--- /dev/null
+++ b/source/core/slang-platform.cpp
@@ -0,0 +1,172 @@
+// slang-platform.cpp
+#include "slang-platform.h"
+
+#include "slang-common.h"
+
+#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #define NOMINMAX
+ #include <Windows.h>
+ #undef WIN32_LEAN_AND_MEAN
+ #undef NOMINMAX
+#else
+ #include "slang-string.h"
+ #include <dlfcn.h>
+#endif
+
+namespace Slang
+{
+ // SharedLibrary
+
+/* static */SlangResult SharedLibrary::load(const char* filename, SharedLibrary::Handle& handleOut)
+{
+ StringBuilder builder;
+ appendPlatformFileName(UnownedStringSlice(filename), builder);
+ return loadWithPlatformFilename(builder.begin(), handleOut);
+}
+
+#ifdef _WIN32
+
+// Make sure SlangResult match for common standard window HRESULT
+SLANG_COMPILE_TIME_ASSERT(E_FAIL == SLANG_FAIL);
+SLANG_COMPILE_TIME_ASSERT(E_NOINTERFACE == SLANG_E_NO_INTERFACE);
+SLANG_COMPILE_TIME_ASSERT(E_HANDLE == SLANG_E_INVALID_HANDLE);
+SLANG_COMPILE_TIME_ASSERT(E_NOTIMPL == SLANG_E_NOT_IMPLEMENTED);
+SLANG_COMPILE_TIME_ASSERT(E_INVALIDARG == SLANG_E_INVALID_ARG);
+SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY);
+
+/* static */SlangResult PlatformUtil::appendResult(SlangResult res, StringBuilder& builderOut)
+{
+ if (SLANG_FAILED(res) && res != SLANG_FAIL)
+ {
+ LPWSTR buffer = nullptr;
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ nullptr,
+ res,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPWSTR)&buffer,
+ 0,
+ nullptr);
+
+ if (buffer)
+ {
+ builderOut << " ";
+ // Convert to string
+ builderOut.Append(String::fromWString(buffer));
+ LocalFree(buffer);
+ return SLANG_OK;
+ }
+ }
+ return SLANG_FAIL;
+}
+
+/* static */SlangResult SharedLibrary::loadWithPlatformFilename(char const* platformFileName, SharedLibrary::Handle& handleOut)
+{
+ handleOut = nullptr;
+ // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibrarya
+ const HMODULE h = LoadLibraryA(platformFileName);
+ if (!h)
+ {
+ const DWORD lastError = GetLastError();
+ switch (lastError)
+ {
+ case ERROR_MOD_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_FILE_NOT_FOUND:
+ {
+ return SLANG_E_NOT_FOUND;
+ }
+ case ERROR_INVALID_ACCESS:
+ case ERROR_ACCESS_DENIED:
+ case ERROR_INVALID_DATA:
+ {
+ return SLANG_E_CANNOT_OPEN;
+ }
+ default: break;
+ }
+ // Turn to Result, if not one of the well known errors
+ return HRESULT_FROM_WIN32(lastError);
+ }
+ handleOut = (Handle)h;
+ return SLANG_OK;
+}
+
+/* static */void SharedLibrary::unload(Handle handle)
+{
+ SLANG_ASSERT(handle);
+ ::FreeLibrary((HMODULE)handle);
+}
+
+/* static */SharedLibrary::FuncPtr SharedLibrary::findFuncByName(Handle handle, char const* name)
+{
+ SLANG_ASSERT(handle);
+ return (FuncPtr)GetProcAddress((HMODULE)handle, name);
+}
+
+/* static */void SharedLibrary::appendPlatformFileName(const UnownedStringSlice& name, StringBuilder& dst)
+{
+ // Windows doesn't need the extension or any prefix to work
+ dst.Append(name);
+}
+
+#else // _WIN32
+
+/* static */SlangResult PlatformUtil::appendResult(SlangResult res, StringBuilder& builderOut)
+{
+ return SLANG_E_NOT_IMPLEMENTED;
+}
+
+/* static */SlangResult SharedLibrary::loadWithPlatformFilename(char const* platformFileName, Handle& handleOut)
+{
+ handleOut = nullptr;
+
+ void* h = dlopen(platformFileName, RTLD_NOW | RTLD_LOCAL);
+ if(!h)
+ {
+#if 0
+ // We can't output the error message here, because it will cause output when testing what code gen is available
+ if(auto msg = dlerror())
+ {
+ fprintf(stderr, "error: %s\n", msg);
+ }
+#endif
+ return SLANG_FAIL;
+ }
+ handleOut = (Handle)h;
+ return SLANG_OK;
+}
+
+/* static */void SharedLibrary::unload(Handle handle)
+{
+ SLANG_ASSERT(handle);
+ dlclose(handle);
+}
+
+/* static */SharedLibrary::FuncPtr SharedLibrary::findFuncByName(Handle handle, char const* name)
+{
+ SLANG_ASSERT(handle);
+ return (FuncPtr)dlsym((void*)handle, name);
+}
+
+/* static */void SharedLibrary::appendPlatformFileName(const UnownedStringSlice& name, StringBuilder& dst)
+{
+#if __CYGWIN__
+ dst.Append(name);
+ dst.Append(".dll");
+#elif SLANG_APPLE_FAMILY
+ dst.Append("lib");
+ dst.Append(name);
+ dst.Append(".dylib");
+#elif SLANG_LINUX_FAMILY
+ dst.Append("lib");
+ dst.Append(name);
+ dst.Append(".so");
+#else
+ // Just guess we can do with the name on it's own
+ dst.Append(name);
+#endif
+}
+
+#endif // _WIN32
+
+}