diff options
Diffstat (limited to 'lexilla/test/LexillaAccess.cxx')
-rw-r--r-- | lexilla/test/LexillaAccess.cxx | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/lexilla/test/LexillaAccess.cxx b/lexilla/test/LexillaAccess.cxx new file mode 100644 index 000000000..ea62c9605 --- /dev/null +++ b/lexilla/test/LexillaAccess.cxx @@ -0,0 +1,95 @@ +// Scintilla source code edit control +/** @file LexillaAccess.cxx + ** Interface to Lexilla shared library. + **/ + // Copyright 2019 by Neil Hodgson <neilh@scintilla.org> + // The License.txt file describes the conditions under which this software may be distributed. + +#include <cstring> + +#include <iterator> + +#include <iostream> +#include <filesystem> + +#if !_WIN32 +#include <dlfcn.h> +#else +#include <windows.h> +#endif + +#include "ILexer.h" + +#include "Lexilla.h" + +#include "LexillaAccess.h" + +#if _WIN32 +#define EXT_LEXER_DECL __stdcall +typedef FARPROC Function; +typedef HMODULE Module; +#else +#define EXT_LEXER_DECL +typedef void *Function; +typedef void *Module; +#endif + +typedef Scintilla::ILexer5 *(EXT_LEXER_DECL *CreateLexerFn)(const char *name); + +Module lexillaDL {}; + +/// Generic function to convert from a Function(void* or FARPROC) to a function pointer. +/// This avoids undefined and conditionally defined behaviour. +template<typename T> +T FunctionPointer(Function function) noexcept { + static_assert(sizeof(T) == sizeof(function)); + T fp; + memcpy(&fp, &function, sizeof(T)); + return fp; +} + +CreateLexerFn fnCL; + +Function FindSymbol(const char *symbol) noexcept { +#if _WIN32 + return ::GetProcAddress(lexillaDL, symbol); +#else + return dlsym(lexillaDL, symbol); +#endif +} + +Scintilla::ILexer5 *CreateLexer(std::string languageName) { +#ifdef LEXILLA_STATIC + return CreateLexer(languageName.c_str()); +#else + return fnCL(languageName.c_str()); +#endif +} + +bool LoadLexilla([[maybe_unused]] std::filesystem::path path) { +#ifdef LEXILLA_STATIC + return true; +#else + std::filesystem::path sharedLibrary = path; + sharedLibrary.append("bin"); +#if _WIN32 + sharedLibrary.append("lexilla.dll"); + lexillaDL = ::LoadLibraryW(sharedLibrary.c_str()); +#else +#if defined(__APPLE__) + sharedLibrary.append("lexilla.dylib"); +#else + sharedLibrary.append("lexilla.so"); +#endif + lexillaDL = dlopen(sharedLibrary.c_str(), RTLD_LAZY); +#endif + + if (lexillaDL) { + fnCL = FunctionPointer<CreateLexerFn>(FindSymbol("CreateLexer")); + } else { + std::cout << "Cannot load " << sharedLibrary.string() << "\n"; + } + + return lexillaDL && fnCL; +#endif +} |