diff --git a/CMakeLists.txt b/CMakeLists.txt index c36a42dd8..3c2f586d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,17 @@ target_sources(scratchcpp include(FetchContent) +# Compiler options +target_compile_options(scratchcpp PRIVATE + -fvisibility=hidden + -fvisibility-inlines-hidden +) + +target_link_options(scratchcpp PRIVATE + -Wl,--exclude-libs,ALL + -Wl,-Bsymbolic +) + # zip include(build/zip.cmake) target_link_libraries(scratchcpp PRIVATE zip) @@ -139,7 +150,11 @@ target_compile_definitions(scratchcpp PRIVATE LIBSCRATCHCPP_VERSION_MINOR=${PROJ target_compile_definitions(scratchcpp PRIVATE LIBSCRATCHCPP_VERSION_PATCH=${PROJECT_VERSION_PATCH}) # Unit tests +target_link_libraries(scratchcpp PRIVATE scratchcpp-test-export) + if (LIBSCRATCHCPP_BUILD_UNIT_TESTS) + target_compile_definitions(scratchcpp-test-export INTERFACE LIBSCRATCHCPP_TEST) + enable_testing() add_subdirectory(test) endif() diff --git a/build/HunterPackages.cmake b/build/HunterPackages.cmake index 7bf566f30..38bb47bdf 100644 --- a/build/HunterPackages.cmake +++ b/build/HunterPackages.cmake @@ -12,11 +12,47 @@ set(HUNTER_LLVM_VERSION 19.1.0) set(HUNTER_LLVM_CMAKE_ARGS LLVM_ENABLE_CRASH_OVERRIDES=OFF LLVM_ENABLE_ZLIB=OFF + LLVM_ENABLE_ZSTD=OFF + LLVM_ENABLE_TERMINFO=OFF LLVM_ENABLE_RTTI=ON - LLVM_BUILD_EXAMPLES=OFF + LLVM_BUILD_LLVM_DYLIB=OFF + LLVM_BUILD_RUNTIME=OFF + LLVM_BUILD_RUNTIMES=OFF + LLVM_BUILD_TESTS=OFF LLVM_BUILD_TOOLS=OFF - LLVM_BUILD_LLVM_DYLIB=ON + LLVM_BUILD_UTILS=OFF + LLVM_INCLUDE_BENCHMARKS=OFF + LLVM_INCLUDE_DOCS=OFF LLVM_INCLUDE_EXAMPLES=OFF + LLVM_INCLUDE_RUNTIMES=OFF + LLVM_INCLUDE_TESTS=OFF + LLVM_INCLUDE_TOOLS=FALSE + LLVM_INCLUDE_UTILS=OFF + LLVM_ENABLE_PLUGINS=OFF + LLVM_ENABLE_BINDINGS=OFF + LLVM_ENABLE_OCAMLDOC=OFF + LLVM_BUILD_LLJIT=OFF + LLVM_BUILD_ORC_JIT=OFF + LLVM_TOOL_LTO_BUILD=OFF + LLVM_TOOL_GOLD_BUILD=OFF + LLVM_TOOL_BUGPOINT_BUILD=OFF + LLVM_TOOL_CLANG_BUILD=OFF + LLVM_TOOL_LLDB_BUILD=OFF + LLVM_TOOL_LLI_BUILD=OFF + LLVM_TOOL_LLVM_AR_BUILD=OFF + LLVM_TOOL_LLVM_AS_BUILD=OFF + LLVM_TOOL_LLVM_BCANALYZER_BUILD=OFF + LLVM_TOOL_LLVM_CAT_BUILD=OFF + LLVM_TOOL_LLVM_CFI_VERIFY_BUILD=OFF + LLVM_TOOL_LLVM_CONFIG_BUILD=OFF + LLVM_TOOL_LLVM_COV_BUILD=OFF + LLVM_TOOL_LLVM_CVTRES_BUILD=OFF + LLVM_TOOL_LLVM_EXTRACT_BUILD=OFF + LLVM_TOOL_LLVM_LTO_BUILD=OFF + LLVM_TOOL_LLVM_LINK_BUILD=OFF + LLVM_TOOL_LLVM_SIZE_BUILD=OFF + LLVM_TOOL_LLVM_STRINGS_BUILD=OFF + LLVM_TOOL_LLVM_SYMBOLIZER_BUILD=OFF LLVM_TARGETS_TO_BUILD=host ) diff --git a/include/scratchcpp/compiler.h b/include/scratchcpp/compiler.h index 2b48866d3..7cc8d44d9 100644 --- a/include/scratchcpp/compiler.h +++ b/include/scratchcpp/compiler.h @@ -9,6 +9,8 @@ #include "enum_bitmask.h" #include "spimpl.h" +#define BLOCK_EXPORT extern "C" LIBSCRATCHCPP_EXPORT + namespace libscratchcpp { diff --git a/include/scratchcpp/value_functions.h b/include/scratchcpp/value_functions.h index f8f983bbe..7e1274b18 100644 --- a/include/scratchcpp/value_functions.h +++ b/include/scratchcpp/value_functions.h @@ -48,55 +48,55 @@ inline constexpr Rgb rgba(int r, int g, int b, int a) extern "C" { - LIBSCRATCHCPP_EXPORT void value_free(ValueData *v); - - LIBSCRATCHCPP_EXPORT void value_init(ValueData *v); - - LIBSCRATCHCPP_EXPORT void value_assign_double(ValueData *v, double numberValue); - LIBSCRATCHCPP_EXPORT void value_assign_bool(ValueData *v, bool boolValue); - LIBSCRATCHCPP_EXPORT void value_assign_string(ValueData *v, const std::string &stringValue); - LIBSCRATCHCPP_EXPORT void value_assign_cstring(ValueData *v, const char *stringValue); - LIBSCRATCHCPP_EXPORT void value_assign_stringPtr(ValueData *v, const StringPtr *stringValue); - LIBSCRATCHCPP_EXPORT void value_assign_pointer(ValueData *v, const void *pointerValue); - LIBSCRATCHCPP_EXPORT void value_assign_copy(ValueData *v, const ValueData *another); - - LIBSCRATCHCPP_EXPORT bool value_isInfinity(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isNegativeInfinity(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isNaN(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isNumber(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isValidNumber(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isInt(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isBool(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isString(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_isPointer(const ValueData *v); - - LIBSCRATCHCPP_EXPORT long value_toLong(const ValueData *v); - LIBSCRATCHCPP_EXPORT int value_toInt(const ValueData *v); - LIBSCRATCHCPP_EXPORT double value_toDouble(const ValueData *v); - LIBSCRATCHCPP_EXPORT bool value_toBool(const ValueData *v); - LIBSCRATCHCPP_EXPORT void value_toString(const ValueData *v, std::string *dst); - LIBSCRATCHCPP_EXPORT void value_toStringPtr(const ValueData *v, StringPtr *dst); - LIBSCRATCHCPP_EXPORT void value_toUtf16(const ValueData *v, std::u16string *dst); - LIBSCRATCHCPP_EXPORT Rgb value_toRgba(const ValueData *v); - LIBSCRATCHCPP_EXPORT const void *value_toPointer(const ValueData *v); - - LIBSCRATCHCPP_EXPORT bool value_doubleIsInt(double v); - - LIBSCRATCHCPP_EXPORT void value_doubleToStringPtr(double v, StringPtr *dst); - LIBSCRATCHCPP_EXPORT const StringPtr *value_boolToStringPtr(bool v); - LIBSCRATCHCPP_EXPORT double value_stringToDouble(const StringPtr *s); - LIBSCRATCHCPP_EXPORT double value_stringToDoubleWithCheck(const StringPtr *s, bool *ok); - LIBSCRATCHCPP_EXPORT bool value_stringToBool(const StringPtr *s); - - LIBSCRATCHCPP_EXPORT void value_add(const ValueData *v1, const ValueData *v2, ValueData *dst); - LIBSCRATCHCPP_EXPORT void value_subtract(const ValueData *v1, const ValueData *v2, ValueData *dst); - LIBSCRATCHCPP_EXPORT void value_multiply(const ValueData *v1, const ValueData *v2, ValueData *dst); - LIBSCRATCHCPP_EXPORT void value_divide(const ValueData *v1, const ValueData *v2, ValueData *dst); - LIBSCRATCHCPP_EXPORT void value_mod(const ValueData *v1, const ValueData *v2, ValueData *dst); - - LIBSCRATCHCPP_EXPORT bool value_equals(const ValueData *v1, const ValueData *v2); - LIBSCRATCHCPP_EXPORT bool value_greater(const ValueData *v1, const ValueData *v2); - LIBSCRATCHCPP_EXPORT bool value_lower(const ValueData *v1, const ValueData *v2); + void value_free(ValueData *v); + + void value_init(ValueData *v); + + void value_assign_double(ValueData *v, double numberValue); + void value_assign_bool(ValueData *v, bool boolValue); + void value_assign_string(ValueData *v, const std::string &stringValue); + void value_assign_cstring(ValueData *v, const char *stringValue); + void value_assign_stringPtr(ValueData *v, const StringPtr *stringValue); + void value_assign_pointer(ValueData *v, const void *pointerValue); + void value_assign_copy(ValueData *v, const ValueData *another); + + bool value_isInfinity(const ValueData *v); + bool value_isNegativeInfinity(const ValueData *v); + bool value_isNaN(const ValueData *v); + bool value_isNumber(const ValueData *v); + bool value_isValidNumber(const ValueData *v); + bool value_isInt(const ValueData *v); + bool value_isBool(const ValueData *v); + bool value_isString(const ValueData *v); + bool value_isPointer(const ValueData *v); + + long value_toLong(const ValueData *v); + int value_toInt(const ValueData *v); + double value_toDouble(const ValueData *v); + bool value_toBool(const ValueData *v); + void value_toString(const ValueData *v, std::string *dst); + void value_toStringPtr(const ValueData *v, StringPtr *dst); + void value_toUtf16(const ValueData *v, std::u16string *dst); + Rgb value_toRgba(const ValueData *v); + const void *value_toPointer(const ValueData *v); + + bool value_doubleIsInt(double v); + + void value_doubleToStringPtr(double v, StringPtr *dst); + const StringPtr *value_boolToStringPtr(bool v); + double value_stringToDouble(const StringPtr *s); + double value_stringToDoubleWithCheck(const StringPtr *s, bool *ok); + bool value_stringToBool(const StringPtr *s); + + void value_add(const ValueData *v1, const ValueData *v2, ValueData *dst); + void value_subtract(const ValueData *v1, const ValueData *v2, ValueData *dst); + void value_multiply(const ValueData *v1, const ValueData *v2, ValueData *dst); + void value_divide(const ValueData *v1, const ValueData *v2, ValueData *dst); + void value_mod(const ValueData *v1, const ValueData *v2, ValueData *dst); + + bool value_equals(const ValueData *v1, const ValueData *v2); + bool value_greater(const ValueData *v1, const ValueData *v2); + bool value_lower(const ValueData *v1, const ValueData *v2); } } // namespace libscratchcpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0d63d5d7e..b11cb6a7f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,13 @@ target_sources(scratchcpp rect_p.h ) +add_library(scratchcpp-test-export + INTERFACE + test_export.h +) + +target_include_directories(scratchcpp-test-export INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + add_subdirectory(blocks) add_subdirectory(engine) add_subdirectory(internal) diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 72d98eb76..7e7105cb8 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -15,6 +15,8 @@ if (LIBSCRATCHCPP_AUDIO_SUPPORT) target_compile_definitions(scratchcpp-audio PUBLIC LIBSCRATCHCPP_AUDIO_SUPPORT) endif() +target_link_libraries(scratchcpp-audio PRIVATE scratchcpp-test-export) + target_sources(scratchcpp-audio PUBLIC iaudioengine.h diff --git a/src/audio/audioinput.h b/src/audio/audioinput.h index 7d59e6e6f..a80bcd6ad 100644 --- a/src/audio/audioinput.h +++ b/src/audio/audioinput.h @@ -2,14 +2,13 @@ #pragma once -#include - #include "iaudioinput.h" +#include "test_export.h" namespace libscratchcpp { -class AudioInput : public IAudioInput +class LIBSCRATCHCPP_TEST_EXPORT AudioInput : public IAudioInput { public: AudioInput(); diff --git a/src/audio/audiooutput.h b/src/audio/audiooutput.h index e331b545a..d78e1b3c5 100644 --- a/src/audio/audiooutput.h +++ b/src/audio/audiooutput.h @@ -3,11 +3,12 @@ #pragma once #include "iaudiooutput.h" +#include "test_export.h" namespace libscratchcpp { -class AudioOutput : public IAudioOutput +class LIBSCRATCHCPP_TEST_EXPORT AudioOutput : public IAudioOutput { public: AudioOutput(); diff --git a/src/audio/iaudioengine.h b/src/audio/iaudioengine.h index 8100334bb..97b026a6e 100644 --- a/src/audio/iaudioengine.h +++ b/src/audio/iaudioengine.h @@ -2,12 +2,12 @@ #pragma once -#include +#include "test_export.h" namespace libscratchcpp { -class IAudioEngine +class LIBSCRATCHCPP_TEST_EXPORT IAudioEngine { public: virtual ~IAudioEngine() { } diff --git a/src/audio/internal/audioengine.h b/src/audio/internal/audioengine.h index 4b030837d..fdbe66077 100644 --- a/src/audio/internal/audioengine.h +++ b/src/audio/internal/audioengine.h @@ -2,8 +2,6 @@ #pragma once -#include - #include "../iaudioengine.h" struct ma_engine; @@ -12,7 +10,7 @@ namespace libscratchcpp { // This is a singleton which initializes and uninitializes the miniaudio engine -class AudioEngine : public IAudioEngine +class LIBSCRATCHCPP_TEST_EXPORT AudioEngine : public IAudioEngine { public: AudioEngine(); diff --git a/src/audio/internal/audioenginestub.h b/src/audio/internal/audioenginestub.h index b6de3c1d5..04471e1fe 100644 --- a/src/audio/internal/audioenginestub.h +++ b/src/audio/internal/audioenginestub.h @@ -3,11 +3,12 @@ #pragma once #include "../iaudioengine.h" +#include "test_export.h" namespace libscratchcpp { -class AudioEngineStub : public IAudioEngine +class LIBSCRATCHCPP_TEST_EXPORT AudioEngineStub : public IAudioEngine { public: friend class IAudioEngine; diff --git a/src/audio/internal/audioloudness.h b/src/audio/internal/audioloudness.h index ea0a71b5f..0d167da37 100644 --- a/src/audio/internal/audioloudness.h +++ b/src/audio/internal/audioloudness.h @@ -3,13 +3,14 @@ #pragma once #include "../iaudioloudness.h" +#include "test_export.h" struct ma_device; namespace libscratchcpp { -class AudioLoudness : public IAudioLoudness +class LIBSCRATCHCPP_TEST_EXPORT AudioLoudness : public IAudioLoudness { public: AudioLoudness(); diff --git a/src/audio/internal/audioloudnessstub.h b/src/audio/internal/audioloudnessstub.h index d8e307a35..edde94b24 100644 --- a/src/audio/internal/audioloudnessstub.h +++ b/src/audio/internal/audioloudnessstub.h @@ -3,11 +3,12 @@ #pragma once #include "../iaudioloudness.h" +#include "test_export.h" namespace libscratchcpp { -class AudioLoudnessStub : public IAudioLoudness +class LIBSCRATCHCPP_TEST_EXPORT AudioLoudnessStub : public IAudioLoudness { public: AudioLoudnessStub(); diff --git a/src/audio/internal/audioplayer.h b/src/audio/internal/audioplayer.h index ad5a2e0db..51c218da1 100644 --- a/src/audio/internal/audioplayer.h +++ b/src/audio/internal/audioplayer.h @@ -3,6 +3,7 @@ #pragma once #include "../iaudioplayer.h" +#include "test_export.h" struct ma_decoder; struct ma_sound; @@ -10,7 +11,7 @@ struct ma_sound; namespace libscratchcpp { -class AudioPlayer : public IAudioPlayer +class LIBSCRATCHCPP_TEST_EXPORT AudioPlayer : public IAudioPlayer { public: AudioPlayer(); diff --git a/src/audio/internal/audioplayerstub.h b/src/audio/internal/audioplayerstub.h index c8c297cf9..fabb588be 100644 --- a/src/audio/internal/audioplayerstub.h +++ b/src/audio/internal/audioplayerstub.h @@ -3,11 +3,12 @@ #pragma once #include "../iaudioplayer.h" +#include "test_export.h" namespace libscratchcpp { -class AudioPlayerStub : public IAudioPlayer +class LIBSCRATCHCPP_TEST_EXPORT AudioPlayerStub : public IAudioPlayer { public: AudioPlayerStub(); diff --git a/src/blocks/controlblocks.cpp b/src/blocks/controlblocks.cpp index 765826316..807d1b78e 100644 --- a/src/blocks/controlblocks.cpp +++ b/src/blocks/controlblocks.cpp @@ -186,35 +186,35 @@ CompilerValue *ControlBlocks::compileDeleteThisClone(Compiler *compiler) return nullptr; } -extern "C" void control_stop_all(ExecutionContext *ctx) +BLOCK_EXPORT void control_stop_all(ExecutionContext *ctx) { ctx->engine()->stop(); } -extern "C" void control_stop_other_scripts_in_target(ExecutionContext *ctx) +BLOCK_EXPORT void control_stop_other_scripts_in_target(ExecutionContext *ctx) { Thread *thread = ctx->thread(); ctx->engine()->stopTarget(thread->target(), thread); } -extern "C" void control_start_wait(ExecutionContext *ctx, double seconds) +BLOCK_EXPORT void control_start_wait(ExecutionContext *ctx, double seconds) { ctx->stackTimer()->start(seconds); ctx->engine()->requestRedraw(); } -extern "C" bool control_stack_timer_elapsed(ExecutionContext *ctx) +BLOCK_EXPORT bool control_stack_timer_elapsed(ExecutionContext *ctx) { return ctx->stackTimer()->elapsed(); } -extern "C" void control_create_clone_of_myself(Target *target) +BLOCK_EXPORT void control_create_clone_of_myself(Target *target) { if (!target->isStage()) static_cast(target)->clone(); } -extern "C" void control_create_clone_by_index(ExecutionContext *ctx, double index) +BLOCK_EXPORT void control_create_clone_by_index(ExecutionContext *ctx, double index) { Target *target = ctx->engine()->targetAt(index); @@ -222,7 +222,7 @@ extern "C" void control_create_clone_by_index(ExecutionContext *ctx, double inde static_cast(target)->clone(); } -extern "C" void control_create_clone(ExecutionContext *ctx, const StringPtr *spriteName) +BLOCK_EXPORT void control_create_clone(ExecutionContext *ctx, const StringPtr *spriteName) { static const StringPtr myself("_myself_"); @@ -239,7 +239,7 @@ extern "C" void control_create_clone(ExecutionContext *ctx, const StringPtr *spr } } -extern "C" bool control_delete_this_clone(Target *target) +BLOCK_EXPORT bool control_delete_this_clone(Target *target) { if (!target->isStage()) { Sprite *sprite = static_cast(target); diff --git a/src/blocks/controlblocks.h b/src/blocks/controlblocks.h index 0f44982c5..f2e2cf8e5 100644 --- a/src/blocks/controlblocks.h +++ b/src/blocks/controlblocks.h @@ -4,10 +4,12 @@ #include +#include "test_export.h" + namespace libscratchcpp { -class ControlBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT ControlBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/customblocks.h b/src/blocks/customblocks.h index b2a2613f7..ee4d67d32 100644 --- a/src/blocks/customblocks.h +++ b/src/blocks/customblocks.h @@ -4,10 +4,12 @@ #include +#include "test_export.h" + namespace libscratchcpp { -class CustomBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT CustomBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/eventblocks.cpp b/src/blocks/eventblocks.cpp index 51c445b6e..61177510b 100644 --- a/src/blocks/eventblocks.cpp +++ b/src/blocks/eventblocks.cpp @@ -173,7 +173,17 @@ CompilerValue *EventBlocks::compileWhenKeyPressed(Compiler *compiler) return nullptr; } -extern "C" bool event_whentouchingobject_predicate(Target *target, const StringPtr *name) +IAudioInput *EventBlocks::audioInput() +{ + return m_audioInput; +} + +void EventBlocks::setAudioInput(IAudioInput *audioInput) +{ + m_audioInput = audioInput; +} + +BLOCK_EXPORT bool event_whentouchingobject_predicate(Target *target, const StringPtr *name) { static const StringPtr MOUSE_STR = StringPtr("_mouse_"); static const StringPtr EDGE_STR = StringPtr("_edge_"); @@ -196,21 +206,21 @@ extern "C" bool event_whentouchingobject_predicate(Target *target, const StringP } } -extern "C" bool event_whengreaterthan_loudness_predicate(ExecutionContext *ctx, double value) +BLOCK_EXPORT bool event_whengreaterthan_loudness_predicate(ExecutionContext *ctx, double value) { - if (!EventBlocks::audioInput) - EventBlocks::audioInput = AudioInput::instance().get(); + if (!EventBlocks::audioInput()) + EventBlocks::setAudioInput(AudioInput::instance().get()); - auto audioLoudness = EventBlocks::audioInput->audioLoudness(); + auto audioLoudness = EventBlocks::audioInput()->audioLoudness(); return (audioLoudness->getLoudness() > value); } -extern "C" bool event_whengreaterthan_timer_predicate(ExecutionContext *ctx, double value) +BLOCK_EXPORT bool event_whengreaterthan_timer_predicate(ExecutionContext *ctx, double value) { return ctx->engine()->timer()->value() > value; } -extern "C" void event_broadcast(ExecutionContext *ctx, const StringPtr *name, bool wait) +BLOCK_EXPORT void event_broadcast(ExecutionContext *ctx, const StringPtr *name, bool wait) { Thread *thread = ctx->thread(); IEngine *engine = thread->engine(); diff --git a/src/blocks/eventblocks.h b/src/blocks/eventblocks.h index 360eff7d2..67970fb40 100644 --- a/src/blocks/eventblocks.h +++ b/src/blocks/eventblocks.h @@ -4,12 +4,14 @@ #include +#include "test_export.h" + namespace libscratchcpp { class IAudioInput; -class EventBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT EventBlocks : public IExtension { public: std::string name() const override; @@ -18,7 +20,8 @@ class EventBlocks : public IExtension void registerBlocks(IEngine *engine) override; - static inline IAudioInput *audioInput = nullptr; + static IAudioInput *audioInput(); + static void setAudioInput(IAudioInput *audioInput); private: static CompilerValue *compileWhenTouchingObject(Compiler *compiler); @@ -33,6 +36,8 @@ class EventBlocks : public IExtension static CompilerValue *compileBroadcast(Compiler *compiler); static CompilerValue *compileBroadcastAndWait(Compiler *compiler); static CompilerValue *compileWhenKeyPressed(Compiler *compiler); + + static inline IAudioInput *m_audioInput = nullptr; }; } // namespace libscratchcpp diff --git a/src/blocks/listblocks.cpp b/src/blocks/listblocks.cpp index 70430d7d9..146aabc33 100644 --- a/src/blocks/listblocks.cpp +++ b/src/blocks/listblocks.cpp @@ -259,7 +259,7 @@ const std::string &ListBlocks::listContentsMonitorName(Block *block) return empty; } -extern "C" void data_showlist(Target *target, List *list) +BLOCK_EXPORT void data_showlist(Target *target, List *list) { Monitor *monitor = list->monitor(); @@ -289,7 +289,7 @@ extern "C" void data_showlist(Target *target, List *list) monitor->setVisible(true); } -extern "C" void data_hidelist(Target *target, List *list) +BLOCK_EXPORT void data_hidelist(Target *target, List *list) { Monitor *monitor = list->monitor(); diff --git a/src/blocks/listblocks.h b/src/blocks/listblocks.h index a6746be1e..9c6704377 100644 --- a/src/blocks/listblocks.h +++ b/src/blocks/listblocks.h @@ -4,12 +4,14 @@ #include +#include "test_export.h" + namespace libscratchcpp { class List; -class ListBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT ListBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/looksblocks.cpp b/src/blocks/looksblocks.cpp index 44297fd04..7d3cb3b0b 100644 --- a/src/blocks/looksblocks.cpp +++ b/src/blocks/looksblocks.cpp @@ -338,7 +338,7 @@ CompilerValue *LooksBlocks::compileNextBackdrop(Compiler *compiler) return nullptr; } -extern "C" void looks_start_stack_timer(ExecutionContext *ctx, double duration) +BLOCK_EXPORT void looks_start_stack_timer(ExecutionContext *ctx, double duration) { ctx->stackTimer()->start(duration); } @@ -356,7 +356,7 @@ void looks_show_bubble(Thread *thread, TextBubble::Type type, const StringPtr *m target->bubble()->setText(u8message); } -extern "C" bool looks_update_bubble(ExecutionContext *ctx) +BLOCK_EXPORT bool looks_update_bubble(ExecutionContext *ctx) { if (ctx->stackTimer()->elapsed()) { Thread *thread = ctx->thread(); @@ -372,57 +372,57 @@ extern "C" bool looks_update_bubble(ExecutionContext *ctx) return false; } -extern "C" void looks_say(ExecutionContext *ctx, const StringPtr *message, bool saveThread) +BLOCK_EXPORT void looks_say(ExecutionContext *ctx, const StringPtr *message, bool saveThread) { looks_show_bubble(ctx->thread(), TextBubble::Type::Say, message, saveThread); } -extern "C" void looks_think(ExecutionContext *ctx, const StringPtr *message, bool saveThread) +BLOCK_EXPORT void looks_think(ExecutionContext *ctx, const StringPtr *message, bool saveThread) { looks_show_bubble(ctx->thread(), TextBubble::Type::Think, message, saveThread); } -extern "C" void looks_show(Sprite *sprite) +BLOCK_EXPORT void looks_show(Sprite *sprite) { sprite->setVisible(true); } -extern "C" void looks_hide(Sprite *sprite) +BLOCK_EXPORT void looks_hide(Sprite *sprite) { sprite->setVisible(false); } -extern "C" void looks_changeeffectby(Target *target, IGraphicsEffect *effect, double change) +BLOCK_EXPORT void looks_changeeffectby(Target *target, IGraphicsEffect *effect, double change) { target->setGraphicsEffectValue(effect, target->graphicsEffectValue(effect) + change); } -extern "C" void looks_seteffectto(Target *target, IGraphicsEffect *effect, double value) +BLOCK_EXPORT void looks_seteffectto(Target *target, IGraphicsEffect *effect, double value) { target->setGraphicsEffectValue(effect, value); } -extern "C" void looks_cleargraphiceffects(Target *target) +BLOCK_EXPORT void looks_cleargraphiceffects(Target *target) { target->clearGraphicsEffects(); } -extern "C" void looks_changesizeby(Sprite *sprite, double change) +BLOCK_EXPORT void looks_changesizeby(Sprite *sprite, double change) { sprite->setSize(sprite->size() + change); } -extern "C" void looks_setsizeto(Sprite *sprite, double size) +BLOCK_EXPORT void looks_setsizeto(Sprite *sprite, double size) { sprite->setSize(size); } -extern "C" double looks_size(Sprite *sprite) +BLOCK_EXPORT double looks_size(Sprite *sprite) { return sprite->size(); } -extern "C" void looks_set_costume_by_index(Target *target, long index) +BLOCK_EXPORT void looks_set_costume_by_index(Target *target, long index) { const int costumeCount = target->costumes().size(); @@ -434,12 +434,12 @@ extern "C" void looks_set_costume_by_index(Target *target, long index) target->setCostumeIndex(index); } -extern "C" void looks_nextcostume(Target *target) +BLOCK_EXPORT void looks_nextcostume(Target *target) { looks_set_costume_by_index(target, target->costumeIndex() + 1); } -extern "C" void looks_previouscostume(Target *target) +BLOCK_EXPORT void looks_previouscostume(Target *target) { looks_set_costume_by_index(target, target->costumeIndex() - 1); } @@ -452,7 +452,7 @@ void looks_randomcostume(Target *target, IRandomGenerator *rng) looks_set_costume_by_index(target, rng->randintExcept(0, count - 1, target->costumeIndex())); // exclude current costume } -extern "C" void looks_switchcostumeto(Target *target, const ValueData *costume) +BLOCK_EXPORT void looks_switchcostumeto(Target *target, const ValueData *costume) { // https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413 if (!value_isString(costume)) { @@ -485,7 +485,7 @@ extern "C" void looks_switchcostumeto(Target *target, const ValueData *costume) } } -extern "C" void looks_start_backdrop_scripts(ExecutionContext *ctx, bool wait) +BLOCK_EXPORT void looks_start_backdrop_scripts(ExecutionContext *ctx, bool wait) { IEngine *engine = ctx->engine(); Stage *stage = engine->stage(); @@ -495,7 +495,7 @@ extern "C" void looks_start_backdrop_scripts(ExecutionContext *ctx, bool wait) engine->startBackdropScripts(backdrop->broadcast(), ctx->thread(), wait); } -extern "C" void looks_switchbackdropto(ExecutionContext *ctx, const ValueData *backdrop) +BLOCK_EXPORT void looks_switchbackdropto(ExecutionContext *ctx, const ValueData *backdrop) { Stage *stage = ctx->engine()->stage(); @@ -532,53 +532,53 @@ extern "C" void looks_switchbackdropto(ExecutionContext *ctx, const ValueData *b } } -extern "C" void looks_move_to_front(ExecutionContext *ctx) +BLOCK_EXPORT void looks_move_to_front(ExecutionContext *ctx) { Target *target = ctx->thread()->target(); ctx->engine()->moveDrawableToFront(target); } -extern "C" void looks_move_to_back(ExecutionContext *ctx) +BLOCK_EXPORT void looks_move_to_back(ExecutionContext *ctx) { Target *target = ctx->thread()->target(); ctx->engine()->moveDrawableToBack(target); } -extern "C" void looks_move_forward_layers(ExecutionContext *ctx, double layers) +BLOCK_EXPORT void looks_move_forward_layers(ExecutionContext *ctx, double layers) { Target *target = ctx->thread()->target(); ctx->engine()->moveDrawableForwardLayers(target, layers); } -extern "C" void looks_move_backward_layers(ExecutionContext *ctx, double layers) +BLOCK_EXPORT void looks_move_backward_layers(ExecutionContext *ctx, double layers) { Target *target = ctx->thread()->target(); ctx->engine()->moveDrawableBackwardLayers(target, layers); } -extern "C" double looks_backdrop_number(ExecutionContext *ctx) +BLOCK_EXPORT double looks_backdrop_number(ExecutionContext *ctx) { return ctx->engine()->stage()->costumeIndex() + 1; } -extern "C" void looks_backdrop_name(StringPtr *ret, ExecutionContext *ctx) +BLOCK_EXPORT void looks_backdrop_name(StringPtr *ret, ExecutionContext *ctx) { const std::string &name = ctx->engine()->stage()->currentCostume()->name(); string_assign_cstring(ret, name.c_str()); } -extern "C" double looks_costume_number(Target *target) +BLOCK_EXPORT double looks_costume_number(Target *target) { return target->costumeIndex() + 1; } -extern "C" void looks_costume_name(StringPtr *ret, Target *target) +BLOCK_EXPORT void looks_costume_name(StringPtr *ret, Target *target) { const std::string &name = target->currentCostume()->name(); string_assign_cstring(ret, name.c_str()); } -extern "C" bool looks_backdrop_promise(ExecutionContext *ctx) +BLOCK_EXPORT bool looks_backdrop_promise(ExecutionContext *ctx) { if (ctx->engine()->stage()->costumes().size() > 0) { ctx->setPromise(std::make_shared()); @@ -588,7 +588,7 @@ extern "C" bool looks_backdrop_promise(ExecutionContext *ctx) return false; } -extern "C" void looks_nextbackdrop(ExecutionContext *ctx) +BLOCK_EXPORT void looks_nextbackdrop(ExecutionContext *ctx) { looks_nextcostume(ctx->engine()->stage()); } diff --git a/src/blocks/looksblocks.h b/src/blocks/looksblocks.h index 334202346..f2bcc00cf 100644 --- a/src/blocks/looksblocks.h +++ b/src/blocks/looksblocks.h @@ -4,7 +4,8 @@ #include #include -#include + +#include "test_export.h" namespace libscratchcpp { @@ -13,7 +14,7 @@ class Target; class Thread; class IGraphicsEffect; -class LooksBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT LooksBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/motionblocks.cpp b/src/blocks/motionblocks.cpp index cd8624e83..6acaf7eb3 100644 --- a/src/blocks/motionblocks.cpp +++ b/src/blocks/motionblocks.cpp @@ -354,23 +354,23 @@ CompilerValue *MotionBlocks::compileDirection(Compiler *compiler) return compiler->addTargetFunctionCall("motion_direction", Compiler::StaticType::Number); } -extern "C" void motion_movesteps(Sprite *sprite, double steps) +BLOCK_EXPORT void motion_movesteps(Sprite *sprite, double steps) { double dir = sprite->direction(); sprite->setPosition(sprite->x() + std::sin(dir * pi / 180) * steps, sprite->y() + std::cos(dir * pi / 180) * steps); } -extern "C" void motion_turnright(Sprite *sprite, double degrees) +BLOCK_EXPORT void motion_turnright(Sprite *sprite, double degrees) { sprite->setDirection(sprite->direction() + degrees); } -extern "C" void motion_turnleft(Sprite *sprite, double degrees) +BLOCK_EXPORT void motion_turnleft(Sprite *sprite, double degrees) { sprite->setDirection(sprite->direction() - degrees); } -extern "C" void motion_pointindirection(Sprite *sprite, double direction) +BLOCK_EXPORT void motion_pointindirection(Sprite *sprite, double direction) { sprite->setDirection(direction); } @@ -392,25 +392,25 @@ inline void motion_point_towards_pos(Sprite *sprite, double x, double y) sprite->setDirection((180 / pi) * std::atan(deltaX / deltaY)); } -extern "C" void motion_point_towards_mouse(Sprite *sprite) +BLOCK_EXPORT void motion_point_towards_mouse(Sprite *sprite) { IEngine *engine = sprite->engine(); motion_point_towards_pos(sprite, engine->mouseX(), engine->mouseY()); } -extern "C" void motion_point_towards_random_direction(ExecutionContext *ctx) +BLOCK_EXPORT void motion_point_towards_random_direction(ExecutionContext *ctx) { Sprite *sprite = static_cast(ctx->thread()->target()); IRandomGenerator *rng = ctx->rng(); sprite->setDirection(rng->randint(-180, 179)); } -extern "C" void motion_point_towards_sprite(Sprite *sprite, Sprite *anotherSprite) +BLOCK_EXPORT void motion_point_towards_sprite(Sprite *sprite, Sprite *anotherSprite) { motion_point_towards_pos(sprite, anotherSprite->x(), anotherSprite->y()); } -extern "C" void motion_pointtowards(ExecutionContext *ctx, const StringPtr *towards) +BLOCK_EXPORT void motion_pointtowards(ExecutionContext *ctx, const StringPtr *towards) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr RANDOM_STR("_random_"); @@ -434,18 +434,18 @@ extern "C" void motion_pointtowards(ExecutionContext *ctx, const StringPtr *towa } } -extern "C" void motion_gotoxy(Sprite *sprite, double x, double y) +BLOCK_EXPORT void motion_gotoxy(Sprite *sprite, double x, double y) { sprite->setPosition(x, y); } -extern "C" void motion_go_to_mouse(Sprite *sprite) +BLOCK_EXPORT void motion_go_to_mouse(Sprite *sprite) { IEngine *engine = sprite->engine(); sprite->setPosition(engine->mouseX(), engine->mouseY()); } -extern "C" void motion_go_to_random_pos(ExecutionContext *ctx) +BLOCK_EXPORT void motion_go_to_random_pos(ExecutionContext *ctx) { Sprite *sprite = static_cast(ctx->thread()->target()); IEngine *engine = ctx->engine(); @@ -455,12 +455,12 @@ extern "C" void motion_go_to_random_pos(ExecutionContext *ctx) sprite->setPosition(rng->randintDouble(-stageWidth / 2.0, stageWidth / 2.0), rng->randintDouble(-stageHeight / 2.0, stageHeight / 2.0)); } -extern "C" void motion_go_to_sprite(Sprite *sprite, Sprite *anotherSprite) +BLOCK_EXPORT void motion_go_to_sprite(Sprite *sprite, Sprite *anotherSprite) { sprite->setPosition(anotherSprite->x(), anotherSprite->y()); } -extern "C" void motion_goto(ExecutionContext *ctx, const StringPtr *towards) +BLOCK_EXPORT void motion_goto(ExecutionContext *ctx, const StringPtr *towards) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr RANDOM_STR("_random_"); @@ -484,12 +484,12 @@ extern "C" void motion_goto(ExecutionContext *ctx, const StringPtr *towards) } } -extern "C" void motion_start_glide(ExecutionContext *ctx, double duration) +BLOCK_EXPORT void motion_start_glide(ExecutionContext *ctx, double duration) { ctx->stackTimer()->start(duration); } -extern "C" bool motion_glide(ExecutionContext *ctx, double duration, double startX, double startY, double endX, double endY) +BLOCK_EXPORT bool motion_glide(ExecutionContext *ctx, double duration, double startX, double startY, double endX, double endY) { IStackTimer *timer = ctx->stackTimer(); Target *target = ctx->thread()->target(); @@ -515,39 +515,39 @@ extern "C" bool motion_glide(ExecutionContext *ctx, double duration, double star } } -extern "C" double motion_get_mouse_x(ExecutionContext *ctx) +BLOCK_EXPORT double motion_get_mouse_x(ExecutionContext *ctx) { return ctx->engine()->mouseX(); } -extern "C" double motion_get_mouse_y(ExecutionContext *ctx) +BLOCK_EXPORT double motion_get_mouse_y(ExecutionContext *ctx) { return ctx->engine()->mouseY(); } -extern "C" double motion_get_random_x(ExecutionContext *ctx) +BLOCK_EXPORT double motion_get_random_x(ExecutionContext *ctx) { const int stageWidth = ctx->engine()->stageWidth(); return ctx->rng()->randintDouble(-stageWidth / 2.0, stageWidth / 2.0); } -extern "C" double motion_get_random_y(ExecutionContext *ctx) +BLOCK_EXPORT double motion_get_random_y(ExecutionContext *ctx) { const int stageHeight = ctx->engine()->stageHeight(); return ctx->rng()->randintDouble(-stageHeight / 2.0, stageHeight / 2.0); } -extern "C" double motion_get_sprite_x(ExecutionContext *ctx, Sprite *sprite) +BLOCK_EXPORT double motion_get_sprite_x(ExecutionContext *ctx, Sprite *sprite) { return sprite->x(); } -extern "C" double motion_get_sprite_y(ExecutionContext *ctx, Sprite *sprite) +BLOCK_EXPORT double motion_get_sprite_y(ExecutionContext *ctx, Sprite *sprite) { return sprite->y(); } -extern "C" double motion_get_target_x(ExecutionContext *ctx, const StringPtr *name) +BLOCK_EXPORT double motion_get_target_x(ExecutionContext *ctx, const StringPtr *name) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr RANDOM_STR("_random_"); @@ -570,7 +570,7 @@ extern "C" double motion_get_target_x(ExecutionContext *ctx, const StringPtr *na } } -extern "C" double motion_get_target_y(ExecutionContext *ctx, const StringPtr *name) +BLOCK_EXPORT double motion_get_target_y(ExecutionContext *ctx, const StringPtr *name) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr RANDOM_STR("_random_"); @@ -593,7 +593,7 @@ extern "C" double motion_get_target_y(ExecutionContext *ctx, const StringPtr *na } } -extern "C" bool motion_is_target_valid(ExecutionContext *ctx, const StringPtr *name) +BLOCK_EXPORT bool motion_is_target_valid(ExecutionContext *ctx, const StringPtr *name) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr RANDOM_STR("_random_"); @@ -609,27 +609,27 @@ extern "C" bool motion_is_target_valid(ExecutionContext *ctx, const StringPtr *n } } -extern "C" void motion_changexby(Sprite *sprite, double dx) +BLOCK_EXPORT void motion_changexby(Sprite *sprite, double dx) { sprite->setX(sprite->x() + dx); } -extern "C" void motion_setx(Sprite *sprite, double x) +BLOCK_EXPORT void motion_setx(Sprite *sprite, double x) { sprite->setX(x); } -extern "C" void motion_changeyby(Sprite *sprite, double dy) +BLOCK_EXPORT void motion_changeyby(Sprite *sprite, double dy) { sprite->setY(sprite->y() + dy); } -extern "C" void motion_sety(Sprite *sprite, double y) +BLOCK_EXPORT void motion_sety(Sprite *sprite, double y) { sprite->setY(y); } -extern "C" void motion_ifonedgebounce(Sprite *sprite) +BLOCK_EXPORT void motion_ifonedgebounce(Sprite *sprite) { // https://github.com/scratchfoundation/scratch-vm/blob/c37745e97e6d8a77ad1dc31a943ea728dd17ba78/src/blocks/scratch3_motion.js#L186-L240 IEngine *engine = sprite->engine(); @@ -713,32 +713,32 @@ extern "C" void motion_ifonedgebounce(Sprite *sprite) sprite->setPosition(fencedX, fencedY); } -extern "C" void motion_set_left_right_style(Sprite *sprite) +BLOCK_EXPORT void motion_set_left_right_style(Sprite *sprite) { sprite->setRotationStyle(Sprite::RotationStyle::LeftRight); } -extern "C" void motion_set_do_not_rotate_style(Sprite *sprite) +BLOCK_EXPORT void motion_set_do_not_rotate_style(Sprite *sprite) { sprite->setRotationStyle(Sprite::RotationStyle::DoNotRotate); } -extern "C" void motion_set_all_around_style(Sprite *sprite) +BLOCK_EXPORT void motion_set_all_around_style(Sprite *sprite) { sprite->setRotationStyle(Sprite::RotationStyle::AllAround); } -extern "C" double motion_xposition(Sprite *sprite) +BLOCK_EXPORT double motion_xposition(Sprite *sprite) { return sprite->x(); } -extern "C" double motion_yposition(Sprite *sprite) +BLOCK_EXPORT double motion_yposition(Sprite *sprite) { return sprite->y(); } -extern "C" double motion_direction(Sprite *sprite) +BLOCK_EXPORT double motion_direction(Sprite *sprite) { return sprite->direction(); } diff --git a/src/blocks/motionblocks.h b/src/blocks/motionblocks.h index bf81b123f..63829b579 100644 --- a/src/blocks/motionblocks.h +++ b/src/blocks/motionblocks.h @@ -4,10 +4,12 @@ #include +#include "test_export.h" + namespace libscratchcpp { -class MotionBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT MotionBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/operatorblocks.h b/src/blocks/operatorblocks.h index 647512e6c..847ba7bbc 100644 --- a/src/blocks/operatorblocks.h +++ b/src/blocks/operatorblocks.h @@ -4,12 +4,14 @@ #include +#include "test_export.h" + namespace libscratchcpp { class IRandomGenerator; -class OperatorBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT OperatorBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/sensingblocks.cpp b/src/blocks/sensingblocks.cpp index d60038cbf..47f8c4562 100644 --- a/src/blocks/sensingblocks.cpp +++ b/src/blocks/sensingblocks.cpp @@ -431,23 +431,43 @@ void SensingBlocks::askNextQuestion() engine->questionAsked()(question->question); } -extern "C" bool sensing_touching_mouse(Target *target) +IAudioInput *SensingBlocks::audioInput() +{ + return m_audioInput; +} + +void SensingBlocks::setAudioInput(IAudioInput *audioInput) +{ + m_audioInput = audioInput; +} + +IClock *SensingBlocks::clock() +{ + return m_clock; +} + +void SensingBlocks::setClock(IClock *clock) +{ + m_clock = clock; +} + +BLOCK_EXPORT bool sensing_touching_mouse(Target *target) { IEngine *engine = target->engine(); return target->touchingPoint(engine->mouseX(), engine->mouseY()); } -extern "C" bool sensing_touching_edge(Target *target) +BLOCK_EXPORT bool sensing_touching_edge(Target *target) { return target->touchingEdge(); } -extern "C" bool sensing_touching_sprite(Target *target, Sprite *sprite) +BLOCK_EXPORT bool sensing_touching_sprite(Target *target, Sprite *sprite) { return target->touchingSprite(sprite); } -extern "C" bool sensing_touchingobject(Target *target, const StringPtr *object) +BLOCK_EXPORT bool sensing_touchingobject(Target *target, const StringPtr *object) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr EDGE_STR("_edge_"); @@ -470,12 +490,12 @@ extern "C" bool sensing_touchingobject(Target *target, const StringPtr *object) return false; } -extern "C" bool sensing_touchingcolor(Target *target, const ValueData *color) +BLOCK_EXPORT bool sensing_touchingcolor(Target *target, const ValueData *color) { return target->touchingColor(value_toRgba(color)); } -extern "C" bool sensing_coloristouchingcolor(Target *target, const ValueData *color, const ValueData *color2) +BLOCK_EXPORT bool sensing_coloristouchingcolor(Target *target, const ValueData *color, const ValueData *color2) { return target->touchingColor(value_toRgba(color), value_toRgba(color2)); } @@ -485,18 +505,18 @@ static inline double sensing_distance(double x0, double y0, double x1, double y1 return std::sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); } -extern "C" double sensing_distance_to_mouse(Sprite *sprite) +BLOCK_EXPORT double sensing_distance_to_mouse(Sprite *sprite) { IEngine *engine = sprite->engine(); return sensing_distance(sprite->x(), sprite->y(), engine->mouseX(), engine->mouseY()); } -extern "C" double sensing_distance_to_sprite(Sprite *sprite, Sprite *targetSprite) +BLOCK_EXPORT double sensing_distance_to_sprite(Sprite *sprite, Sprite *targetSprite) { return sensing_distance(sprite->x(), sprite->y(), targetSprite->x(), targetSprite->y()); } -extern "C" double sensing_distanceto(Sprite *sprite, const StringPtr *object) +BLOCK_EXPORT double sensing_distanceto(Sprite *sprite, const StringPtr *object) { static const StringPtr MOUSE_STR("_mouse_"); static const StringPtr STAGE_STR("_stage_"); @@ -516,100 +536,100 @@ extern "C" double sensing_distanceto(Sprite *sprite, const StringPtr *object) return 10000.0; } -extern "C" void sensing_askandwait(ExecutionContext *ctx, const StringPtr *question) +BLOCK_EXPORT void sensing_askandwait(ExecutionContext *ctx, const StringPtr *question) { SensingBlocks::askQuestion(ctx, question); ctx->thread()->setPromise(std::make_shared()); } -extern "C" void sensing_answer(StringPtr *ret, ExecutionContext *ctx) +BLOCK_EXPORT void sensing_answer(StringPtr *ret, ExecutionContext *ctx) { string_assign(ret, ctx->engine()->answer()); } -extern "C" bool sensing_keypressed(ExecutionContext *ctx, const StringPtr *key) +BLOCK_EXPORT bool sensing_keypressed(ExecutionContext *ctx, const StringPtr *key) { // TODO: Use UTF-16 in engine std::string u8name = utf8::utf16to8(std::u16string(key->data)); return ctx->engine()->keyPressed(u8name); } -extern "C" bool sensing_mousedown(ExecutionContext *ctx) +BLOCK_EXPORT bool sensing_mousedown(ExecutionContext *ctx) { return ctx->engine()->mousePressed(); } -extern "C" double sensing_mousex(ExecutionContext *ctx) +BLOCK_EXPORT double sensing_mousex(ExecutionContext *ctx) { return ctx->engine()->mouseX(); } -extern "C" double sensing_mousey(ExecutionContext *ctx) +BLOCK_EXPORT double sensing_mousey(ExecutionContext *ctx) { return ctx->engine()->mouseY(); } -extern "C" void sensing_setdragmode(Sprite *sprite, bool draggable) +BLOCK_EXPORT void sensing_setdragmode(Sprite *sprite, bool draggable) { sprite->setDraggable(draggable); } -extern "C" double sensing_loudness() +BLOCK_EXPORT double sensing_loudness() { - if (!SensingBlocks::audioInput) - SensingBlocks::audioInput = AudioInput::instance().get(); + if (!SensingBlocks::audioInput()) + SensingBlocks::setAudioInput(AudioInput::instance().get()); - auto audioLoudness = SensingBlocks::audioInput->audioLoudness(); + auto audioLoudness = SensingBlocks::audioInput()->audioLoudness(); return audioLoudness->getLoudness(); } -extern "C" double sensing_timer(ITimer *timer) +BLOCK_EXPORT double sensing_timer(ITimer *timer) { return timer->value(); } -extern "C" void sensing_resettimer(ITimer *timer) +BLOCK_EXPORT void sensing_resettimer(ITimer *timer) { timer->reset(); } -extern "C" double sensing_x_position_of_sprite(Sprite *sprite) +BLOCK_EXPORT double sensing_x_position_of_sprite(Sprite *sprite) { return sprite->x(); } -extern "C" double sensing_y_position_of_sprite(Sprite *sprite) +BLOCK_EXPORT double sensing_y_position_of_sprite(Sprite *sprite) { return sprite->y(); } -extern "C" double sensing_direction_of_sprite(Sprite *sprite) +BLOCK_EXPORT double sensing_direction_of_sprite(Sprite *sprite) { return sprite->direction(); } -extern "C" double sensing_costume_number_of_target(Target *target) +BLOCK_EXPORT double sensing_costume_number_of_target(Target *target) { return target->costumeIndex() + 1; } -extern "C" void sensing_costume_name_of_target(StringPtr *ret, Target *target) +BLOCK_EXPORT void sensing_costume_name_of_target(StringPtr *ret, Target *target) { const std::string &name = target->currentCostume()->name(); string_assign_cstring(ret, name.c_str()); } -extern "C" double sensing_size_of_sprite(Sprite *sprite) +BLOCK_EXPORT double sensing_size_of_sprite(Sprite *sprite) { return sprite->size(); } -extern "C" double sensing_volume_of_target(Target *target) +BLOCK_EXPORT double sensing_volume_of_target(Target *target) { return target->volume(); } -extern "C" Target *sensing_get_target(ExecutionContext *ctx, const StringPtr *name) +BLOCK_EXPORT Target *sensing_get_target(ExecutionContext *ctx, const StringPtr *name) { // TODO: Use UTF-16 in engine std::string u8name = utf8::utf16to8(std::u16string(name->data)); @@ -617,7 +637,7 @@ extern "C" Target *sensing_get_target(ExecutionContext *ctx, const StringPtr *na return engine->targetAt(engine->findTarget(u8name)); } -extern "C" double sensing_x_position_of_sprite_with_check(Target *target) +BLOCK_EXPORT double sensing_x_position_of_sprite_with_check(Target *target) { if (target && !target->isStage()) { Sprite *sprite = static_cast(target); @@ -627,7 +647,7 @@ extern "C" double sensing_x_position_of_sprite_with_check(Target *target) return 0.0; } -extern "C" double sensing_y_position_of_sprite_with_check(Target *target) +BLOCK_EXPORT double sensing_y_position_of_sprite_with_check(Target *target) { if (target && !target->isStage()) { Sprite *sprite = static_cast(target); @@ -637,7 +657,7 @@ extern "C" double sensing_y_position_of_sprite_with_check(Target *target) return 0.0; } -extern "C" double sensing_direction_of_sprite_with_check(Target *target) +BLOCK_EXPORT double sensing_direction_of_sprite_with_check(Target *target) { if (target && !target->isStage()) { Sprite *sprite = static_cast(target); @@ -647,7 +667,7 @@ extern "C" double sensing_direction_of_sprite_with_check(Target *target) return 0.0; } -extern "C" double sensing_costume_number_of_sprite_with_check(Target *target) +BLOCK_EXPORT double sensing_costume_number_of_sprite_with_check(Target *target) { if (target && !target->isStage()) return target->costumeIndex() + 1; @@ -655,7 +675,7 @@ extern "C" double sensing_costume_number_of_sprite_with_check(Target *target) return 0.0; } -extern "C" void sensing_costume_name_of_sprite_with_check(StringPtr *ret, Target *target) +BLOCK_EXPORT void sensing_costume_name_of_sprite_with_check(StringPtr *ret, Target *target) { if (target && !target->isStage()) { const std::string &name = target->currentCostume()->name(); @@ -664,7 +684,7 @@ extern "C" void sensing_costume_name_of_sprite_with_check(StringPtr *ret, Target string_assign_cstring(ret, "0"); } -extern "C" double sensing_size_of_sprite_with_check(Target *target) +BLOCK_EXPORT double sensing_size_of_sprite_with_check(Target *target) { if (target && !target->isStage()) { Sprite *sprite = static_cast(target); @@ -674,7 +694,7 @@ extern "C" double sensing_size_of_sprite_with_check(Target *target) return 0.0; } -extern "C" double sensing_backdrop_number_of_stage_with_check(Target *target) +BLOCK_EXPORT double sensing_backdrop_number_of_stage_with_check(Target *target) { if (target && target->isStage()) return target->costumeIndex() + 1; @@ -682,7 +702,7 @@ extern "C" double sensing_backdrop_number_of_stage_with_check(Target *target) return 0.0; } -extern "C" void sensing_backdrop_name_of_stage_with_check(StringPtr *ret, Target *target) +BLOCK_EXPORT void sensing_backdrop_name_of_stage_with_check(StringPtr *ret, Target *target) { if (target && target->isStage()) { const std::string &name = target->currentCostume()->name(); @@ -691,7 +711,7 @@ extern "C" void sensing_backdrop_name_of_stage_with_check(StringPtr *ret, Target string_assign_cstring(ret, ""); } -extern "C" double sensing_volume_of_target_with_check(Target *target) +BLOCK_EXPORT double sensing_volume_of_target_with_check(Target *target) { if (target) return target->volume(); @@ -699,7 +719,7 @@ extern "C" double sensing_volume_of_target_with_check(Target *target) return 0.0; } -extern "C" ValueData sensing_variable_of_target(Target *target, const StringPtr *varName) +BLOCK_EXPORT ValueData sensing_variable_of_target(Target *target, const StringPtr *varName) { if (target) { // TODO: Use UTF-16 in... Target? @@ -722,60 +742,60 @@ extern "C" ValueData sensing_variable_of_target(Target *target, const StringPtr return ret; } -extern "C" double sensing_current_year() +BLOCK_EXPORT double sensing_current_year() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_year + 1900; } -extern "C" double sensing_current_month() +BLOCK_EXPORT double sensing_current_month() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_mon + 1; } -extern "C" double sensing_current_date() +BLOCK_EXPORT double sensing_current_date() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_mday; } -extern "C" double sensing_current_day_of_week() +BLOCK_EXPORT double sensing_current_day_of_week() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_wday + 1; } -extern "C" double sensing_current_hour() +BLOCK_EXPORT double sensing_current_hour() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_hour; } -extern "C" double sensing_current_minute() +BLOCK_EXPORT double sensing_current_minute() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_min; } -extern "C" double sensing_current_second() +BLOCK_EXPORT double sensing_current_second() { time_t now = time(0); tm *ltm = localtime(&now); return ltm->tm_sec; } -extern "C" double sensing_dayssince2000() +BLOCK_EXPORT double sensing_dayssince2000() { - if (!SensingBlocks::clock) - SensingBlocks::clock = Clock::instance().get(); + if (!SensingBlocks::clock()) + SensingBlocks::setClock(Clock::instance().get()); - auto ms = std::chrono::duration_cast(SensingBlocks::clock->currentSystemTime().time_since_epoch()).count(); + auto ms = std::chrono::duration_cast(SensingBlocks::clock()->currentSystemTime().time_since_epoch()).count(); return ms / 86400000.0 - 10957.0; } diff --git a/src/blocks/sensingblocks.h b/src/blocks/sensingblocks.h index a1d274a2e..1902193ad 100644 --- a/src/blocks/sensingblocks.h +++ b/src/blocks/sensingblocks.h @@ -6,6 +6,8 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { @@ -14,7 +16,7 @@ class IClock; class ExecutionContext; class Thread; -class SensingBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT SensingBlocks : public IExtension { public: std::string name() const override; @@ -27,8 +29,11 @@ class SensingBlocks : public IExtension static void clearQuestions(); static void askQuestion(ExecutionContext *ctx, const StringPtr *question); - static inline IAudioInput *audioInput = nullptr; - static inline IClock *clock = nullptr; + static IAudioInput *audioInput(); + static void setAudioInput(IAudioInput *audioInput); + + static IClock *clock(); + static void setClock(IClock *clock); private: struct Question @@ -71,6 +76,9 @@ class SensingBlocks : public IExtension static void askNextQuestion(); static inline std::vector> m_questions; + + static inline IAudioInput *m_audioInput = nullptr; + static inline IClock *m_clock = nullptr; }; } // namespace libscratchcpp diff --git a/src/blocks/soundblocks.cpp b/src/blocks/soundblocks.cpp index 0dd35cdcd..0eca8ccbd 100644 --- a/src/blocks/soundblocks.cpp +++ b/src/blocks/soundblocks.cpp @@ -192,7 +192,7 @@ int sound_get_index(Target *target, const ValueData *sound) return -1; } -extern "C" Sound *sound_play(ExecutionContext *ctx, const ValueData *soundName, bool storeOwner) +BLOCK_EXPORT Sound *sound_play(ExecutionContext *ctx, const ValueData *soundName, bool storeOwner) { Thread *thread = ctx->thread(); Target *target = thread->target(); @@ -207,7 +207,7 @@ extern "C" Sound *sound_play(ExecutionContext *ctx, const ValueData *soundName, return nullptr; } -extern "C" bool sound_is_waiting(ExecutionContext *ctx, Sound *sound) +BLOCK_EXPORT bool sound_is_waiting(ExecutionContext *ctx, Sound *sound) { if (!sound) return false; @@ -215,47 +215,47 @@ extern "C" bool sound_is_waiting(ExecutionContext *ctx, Sound *sound) return sound->owner() == ctx->thread() && sound->isPlaying(); } -extern "C" void sound_stopallsounds(ExecutionContext *ctx) +BLOCK_EXPORT void sound_stopallsounds(ExecutionContext *ctx) { ctx->engine()->stopSounds(); } -extern "C" void sound_set_pitch_effect(Target *target, double value) +BLOCK_EXPORT void sound_set_pitch_effect(Target *target, double value) { target->setSoundEffectValue(Sound::Effect::Pitch, value); } -extern "C" void sound_set_pan_effect(Target *target, double value) +BLOCK_EXPORT void sound_set_pan_effect(Target *target, double value) { target->setSoundEffectValue(Sound::Effect::Pan, value); } -extern "C" void sound_change_pitch_effect(Target *target, double value) +BLOCK_EXPORT void sound_change_pitch_effect(Target *target, double value) { target->setSoundEffectValue(Sound::Effect::Pitch, target->soundEffectValue(Sound::Effect::Pitch) + value); } -extern "C" void sound_change_pan_effect(Target *target, double value) +BLOCK_EXPORT void sound_change_pan_effect(Target *target, double value) { target->setSoundEffectValue(Sound::Effect::Pan, target->soundEffectValue(Sound::Effect::Pan) + value); } -extern "C" void sound_cleareffects(Target *target) +BLOCK_EXPORT void sound_cleareffects(Target *target) { target->clearSoundEffects(); } -extern "C" void sound_changevolumeby(Target *target, double volume) +BLOCK_EXPORT void sound_changevolumeby(Target *target, double volume) { target->setVolume(target->volume() + volume); } -extern "C" void sound_setvolumeto(Target *target, double volume) +BLOCK_EXPORT void sound_setvolumeto(Target *target, double volume) { target->setVolume(volume); } -extern "C" double sound_volume(Target *target) +BLOCK_EXPORT double sound_volume(Target *target) { return target->volume(); } diff --git a/src/blocks/soundblocks.h b/src/blocks/soundblocks.h index 7f04d9c23..7825f858e 100644 --- a/src/blocks/soundblocks.h +++ b/src/blocks/soundblocks.h @@ -4,12 +4,14 @@ #include +#include "test_export.h" + namespace libscratchcpp { class IAudioOutput; -class SoundBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT SoundBlocks : public IExtension { public: std::string name() const override; diff --git a/src/blocks/variableblocks.cpp b/src/blocks/variableblocks.cpp index 949940f2a..55db51e35 100644 --- a/src/blocks/variableblocks.cpp +++ b/src/blocks/variableblocks.cpp @@ -139,7 +139,7 @@ void VariableBlocks::changeVariableMonitorValue(Block *block, const Value &newVa var->setValue(newValue); } -extern "C" void data_showvariable(Target *target, Variable *variable) +BLOCK_EXPORT void data_showvariable(Target *target, Variable *variable) { Monitor *monitor = variable->monitor(); @@ -169,7 +169,7 @@ extern "C" void data_showvariable(Target *target, Variable *variable) monitor->setVisible(true); } -extern "C" void data_hidevariable(Target *target, Variable *variable) +BLOCK_EXPORT void data_hidevariable(Target *target, Variable *variable) { Monitor *monitor = variable->monitor(); diff --git a/src/blocks/variableblocks.h b/src/blocks/variableblocks.h index 9f350f9f9..2d5a97835 100644 --- a/src/blocks/variableblocks.h +++ b/src/blocks/variableblocks.h @@ -4,10 +4,12 @@ #include +#include "test_export.h" + namespace libscratchcpp { -class VariableBlocks : public IExtension +class LIBSCRATCHCPP_TEST_EXPORT VariableBlocks : public IExtension { public: std::string name() const override; diff --git a/src/engine/compiler.cpp b/src/engine/compiler.cpp index 33d97516f..f113998e4 100644 --- a/src/engine/compiler.cpp +++ b/src/engine/compiler.cpp @@ -60,7 +60,7 @@ std::shared_ptr Compiler::compile(Block *startBlock, CodeType co } } - impl->builder = impl->builderFactory->create(impl->ctx, procedurePrototype, codeType); + impl->builder = impl->builderFactory()->create(impl->ctx, procedurePrototype, codeType); impl->substackTree.clear(); impl->substackHit = false; impl->emptySubstack = false; @@ -743,5 +743,5 @@ const std::unordered_set &Compiler::unsupportedBlocks() const std::shared_ptr Compiler::createContext(IEngine *engine, Target *target) { CompilerPrivate::initBuilderFactory(); - return CompilerPrivate::builderFactory->createCtx(engine, target); + return CompilerPrivate::builderFactory()->createCtx(engine, target); } diff --git a/src/engine/compiler_p.cpp b/src/engine/compiler_p.cpp index 55de0af46..fce12ab7f 100644 --- a/src/engine/compiler_p.cpp +++ b/src/engine/compiler_p.cpp @@ -26,8 +26,8 @@ CompilerPrivate::CompilerPrivate(IEngine *engine, Target *target) : void CompilerPrivate::initBuilderFactory() { - if (!builderFactory) - builderFactory = CodeBuilderFactory::instance().get(); + if (!m_builderFactory) + m_builderFactory = CodeBuilderFactory::instance().get(); } void CompilerPrivate::substackEnd() @@ -67,3 +67,13 @@ void CompilerPrivate::substackEnd() if (!block && !substackTree.empty()) substackEnd(); } + +ICodeBuilderFactory *CompilerPrivate::builderFactory() +{ + return m_builderFactory; +} + +void CompilerPrivate::setBuilderFactory(ICodeBuilderFactory *builderFactory) +{ + m_builderFactory = builderFactory; +} diff --git a/src/engine/compiler_p.h b/src/engine/compiler_p.h index 50f98ab22..c0d076606 100644 --- a/src/engine/compiler_p.h +++ b/src/engine/compiler_p.h @@ -6,6 +6,8 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { @@ -17,8 +19,9 @@ class CompilerValue; class ICodeBuilderFactory; class ICodeBuilder; -struct CompilerPrivate +class LIBSCRATCHCPP_TEST_EXPORT CompilerPrivate { + public: enum class SubstackType { Loop, @@ -43,10 +46,15 @@ struct CompilerPrivate bool emptySubstack = false; bool warp = false; - static inline ICodeBuilderFactory *builderFactory = nullptr; std::shared_ptr builder; std::unordered_set unsupportedBlocks; + + static ICodeBuilderFactory *builderFactory(); + static void setBuilderFactory(ICodeBuilderFactory *builderFactory); + + private: + static inline ICodeBuilderFactory *m_builderFactory = nullptr; }; } // namespace libscratchcpp diff --git a/src/engine/internal/clock.h b/src/engine/internal/clock.h index 5eb906bb2..06aa0b154 100644 --- a/src/engine/internal/clock.h +++ b/src/engine/internal/clock.h @@ -3,12 +3,14 @@ #pragma once #include + #include "iclock.h" +#include "test_export.h" namespace libscratchcpp { -class Clock : public IClock +class LIBSCRATCHCPP_TEST_EXPORT Clock : public IClock { public: Clock(); diff --git a/src/engine/internal/engine.h b/src/engine/internal/engine.h index 19e9809d5..2508a4677 100644 --- a/src/engine/internal/engine.h +++ b/src/engine/internal/engine.h @@ -12,6 +12,8 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { @@ -21,7 +23,7 @@ class IAudioEngine; class Thread; class CompilerContext; -class Engine : public IEngine +class LIBSCRATCHCPP_TEST_EXPORT Engine : public IEngine { public: Engine(); diff --git a/src/engine/internal/llvm/llvmbuildutils.h b/src/engine/internal/llvm/llvmbuildutils.h index 27fe2ca53..20a0a1a82 100644 --- a/src/engine/internal/llvm/llvmbuildutils.h +++ b/src/engine/internal/llvm/llvmbuildutils.h @@ -4,6 +4,7 @@ #include +#include "test_export.h" #include "llvmfunctions.h" #include "llvmlocalvariableinfo.h" #include "llvmvariableptr.h" @@ -19,7 +20,7 @@ namespace libscratchcpp class LLVMRegister; class LLVMCoroutine; -class LLVMBuildUtils +class LIBSCRATCHCPP_TEST_EXPORT LLVMBuildUtils { public: enum class Comparison diff --git a/src/engine/internal/llvm/llvmcodeanalyzer.h b/src/engine/internal/llvm/llvmcodeanalyzer.h index 7b65d922b..87668c3b8 100644 --- a/src/engine/internal/llvm/llvmcodeanalyzer.h +++ b/src/engine/internal/llvm/llvmcodeanalyzer.h @@ -5,6 +5,8 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { @@ -12,7 +14,7 @@ class LLVMBuildUtils; class LLVMInstructionList; class LLVMInstruction; -class LLVMCodeAnalyzer +class LIBSCRATCHCPP_TEST_EXPORT LLVMCodeAnalyzer { public: LLVMCodeAnalyzer(const LLVMBuildUtils &utils); diff --git a/src/engine/internal/llvm/llvmcodebuilder.h b/src/engine/internal/llvm/llvmcodebuilder.h index 7fd9b9288..7a85eb34f 100644 --- a/src/engine/internal/llvm/llvmcodebuilder.h +++ b/src/engine/internal/llvm/llvmcodebuilder.h @@ -10,6 +10,7 @@ #include #include "../icodebuilder.h" +#include "test_export.h" #include "llvmbuildutils.h" #include "llvmcodeanalyzer.h" #include "llvminstruction.h" @@ -26,7 +27,7 @@ namespace libscratchcpp class LLVMCompilerContext; class LLVMConstantRegister; -class LLVMCodeBuilder : public ICodeBuilder +class LIBSCRATCHCPP_TEST_EXPORT LLVMCodeBuilder : public ICodeBuilder { public: LLVMCodeBuilder(LLVMCompilerContext *ctx, BlockPrototype *procedurePrototype = nullptr, Compiler::CodeType codeType = Compiler::CodeType::Script); diff --git a/src/engine/internal/llvm/llvmcompilercontext.h b/src/engine/internal/llvm/llvmcompilercontext.h index 0b8d1dcc0..dd5a2607e 100644 --- a/src/engine/internal/llvm/llvmcompilercontext.h +++ b/src/engine/internal/llvm/llvmcompilercontext.h @@ -11,6 +11,8 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { @@ -23,7 +25,7 @@ class LLVMExecutableCode; // NOTE: Change this in LLVMTypes as well using function_id_t = unsigned int; -class LLVMCompilerContext : public CompilerContext +class LIBSCRATCHCPP_TEST_EXPORT LLVMCompilerContext : public CompilerContext { public: LLVMCompilerContext(IEngine *engine, Target *target); diff --git a/src/engine/internal/llvm/llvmexecutablecode.h b/src/engine/internal/llvm/llvmexecutablecode.h index 2b18b445f..62837597d 100644 --- a/src/engine/internal/llvm/llvmexecutablecode.h +++ b/src/engine/internal/llvm/llvmexecutablecode.h @@ -8,13 +8,14 @@ #include #include "llvmcompilercontext.h" +#include "test_export.h" namespace libscratchcpp { class LLVMExecutionContext; -class LLVMExecutableCode : public ExecutableCode +class LIBSCRATCHCPP_TEST_EXPORT LLVMExecutableCode : public ExecutableCode { public: LLVMExecutableCode( diff --git a/src/engine/internal/llvm/llvmexecutioncontext.h b/src/engine/internal/llvm/llvmexecutioncontext.h index 8201af3a7..4af3b8677 100644 --- a/src/engine/internal/llvm/llvmexecutioncontext.h +++ b/src/engine/internal/llvm/llvmexecutioncontext.h @@ -5,13 +5,14 @@ #include #include "llvmcompilercontext.h" +#include "test_export.h" namespace libscratchcpp { struct StringPtr; -class LLVMExecutionContext : public ExecutionContext +class LIBSCRATCHCPP_TEST_EXPORT LLVMExecutionContext : public ExecutionContext { public: LLVMExecutionContext(LLVMCompilerContext *compilerCtx, Thread *thread); diff --git a/src/engine/internal/llvm/llvmfunctions.cpp b/src/engine/internal/llvm/llvmfunctions.cpp index 3c9b518da..b5f90d550 100644 --- a/src/engine/internal/llvm/llvmfunctions.cpp +++ b/src/engine/internal/llvm/llvmfunctions.cpp @@ -11,27 +11,27 @@ using namespace libscratchcpp; extern "C" { - double llvm_random(ExecutionContext *ctx, ValueData *from, ValueData *to) + LIBSCRATCHCPP_EXPORT double llvm_random(ExecutionContext *ctx, ValueData *from, ValueData *to) { return value_isInt(from) && value_isInt(to) ? ctx->rng()->randint(value_toLong(from), value_toLong(to)) : ctx->rng()->randintDouble(value_toDouble(from), value_toDouble(to)); } - double llvm_random_double(ExecutionContext *ctx, double from, double to) + LIBSCRATCHCPP_EXPORT double llvm_random_double(ExecutionContext *ctx, double from, double to) { return value_doubleIsInt(from) && value_doubleIsInt(to) ? ctx->rng()->randint(from, to) : ctx->rng()->randintDouble(from, to); } - int64_t llvm_random_int64(ExecutionContext *ctx, int64_t from, int64_t to) + LIBSCRATCHCPP_EXPORT int64_t llvm_random_int64(ExecutionContext *ctx, int64_t from, int64_t to) { return ctx->rng()->randint(from, to); } - double llvm_random_bool(ExecutionContext *ctx, bool from, bool to) + LIBSCRATCHCPP_EXPORT double llvm_random_bool(ExecutionContext *ctx, bool from, bool to) { return ctx->rng()->randint(from, to); } - StringPtr **llvm_get_string_array(ExecutionContext *ctx, function_id_t functionId) + LIBSCRATCHCPP_EXPORT StringPtr **llvm_get_string_array(ExecutionContext *ctx, function_id_t functionId) { return static_cast(ctx)->getStringArray(functionId); } diff --git a/src/engine/internal/llvm/llvminstructionlist.h b/src/engine/internal/llvm/llvminstructionlist.h index e7cadb9c4..916ba81f5 100644 --- a/src/engine/internal/llvm/llvminstructionlist.h +++ b/src/engine/internal/llvm/llvminstructionlist.h @@ -5,12 +5,14 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { struct LLVMInstruction; -class LLVMInstructionList +class LIBSCRATCHCPP_TEST_EXPORT LLVMInstructionList { public: LLVMInstructionList() = default; diff --git a/src/engine/internal/randomgenerator.h b/src/engine/internal/randomgenerator.h index 1db28b695..4b664143b 100644 --- a/src/engine/internal/randomgenerator.h +++ b/src/engine/internal/randomgenerator.h @@ -6,10 +6,12 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { -class RandomGenerator : public IRandomGenerator +class LIBSCRATCHCPP_TEST_EXPORT RandomGenerator : public IRandomGenerator { public: RandomGenerator(); diff --git a/src/engine/internal/stacktimer.h b/src/engine/internal/stacktimer.h index e99a1a3ad..54f10ea48 100644 --- a/src/engine/internal/stacktimer.h +++ b/src/engine/internal/stacktimer.h @@ -5,12 +5,14 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { class IClock; -class StackTimer : public IStackTimer +class LIBSCRATCHCPP_TEST_EXPORT StackTimer : public IStackTimer { public: StackTimer(); diff --git a/src/engine/internal/timer.h b/src/engine/internal/timer.h index 7b3aed84d..59dbc8b21 100644 --- a/src/engine/internal/timer.h +++ b/src/engine/internal/timer.h @@ -5,12 +5,14 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { class IClock; -class Timer : public ITimer +class LIBSCRATCHCPP_TEST_EXPORT Timer : public ITimer { public: Timer(); diff --git a/src/internal/downloader.h b/src/internal/downloader.h index 22ff0a361..023492069 100644 --- a/src/internal/downloader.h +++ b/src/internal/downloader.h @@ -6,11 +6,12 @@ #include #include "idownloader.h" +#include "test_export.h" namespace libscratchcpp { -class Downloader : public IDownloader +class LIBSCRATCHCPP_TEST_EXPORT Downloader : public IDownloader { public: Downloader(); diff --git a/src/internal/downloaderfactory.h b/src/internal/downloaderfactory.h index 353091ee0..d5bed5efd 100644 --- a/src/internal/downloaderfactory.h +++ b/src/internal/downloaderfactory.h @@ -4,10 +4,12 @@ #include "idownloaderfactory.h" +#include "test_export.h" + namespace libscratchcpp { -class DownloaderFactory : public IDownloaderFactory +class LIBSCRATCHCPP_TEST_EXPORT DownloaderFactory : public IDownloaderFactory { public: DownloaderFactory(); diff --git a/src/internal/projectdownloader.h b/src/internal/projectdownloader.h index 078934587..2dd9a0e0e 100644 --- a/src/internal/projectdownloader.h +++ b/src/internal/projectdownloader.h @@ -7,6 +7,7 @@ #include #include "iprojectdownloader.h" +#include "test_export.h" namespace libscratchcpp { @@ -14,7 +15,7 @@ namespace libscratchcpp class IDownloaderFactory; class IDownloader; -class ProjectDownloader : public IProjectDownloader +class LIBSCRATCHCPP_TEST_EXPORT ProjectDownloader : public IProjectDownloader { public: ProjectDownloader(IDownloaderFactory *downloaderFactory = nullptr); diff --git a/src/internal/projectdownloaderfactory.h b/src/internal/projectdownloaderfactory.h index 93be6a1d4..92d64c468 100644 --- a/src/internal/projectdownloaderfactory.h +++ b/src/internal/projectdownloaderfactory.h @@ -3,11 +3,12 @@ #pragma once #include "iprojectdownloaderfactory.h" +#include "test_export.h" namespace libscratchcpp { -class ProjectDownloaderFactory : public IProjectDownloaderFactory +class LIBSCRATCHCPP_TEST_EXPORT ProjectDownloaderFactory : public IProjectDownloaderFactory { public: ProjectDownloaderFactory(); diff --git a/src/internal/projecturl.h b/src/internal/projecturl.h index dd09b540a..7e75ec3d4 100644 --- a/src/internal/projecturl.h +++ b/src/internal/projecturl.h @@ -4,10 +4,12 @@ #include +#include "test_export.h" + namespace libscratchcpp { -class ProjectUrl +class LIBSCRATCHCPP_TEST_EXPORT ProjectUrl { public: ProjectUrl(const std::string &url); diff --git a/src/internal/zipreader.h b/src/internal/zipreader.h index 546aec69e..e80aafedc 100644 --- a/src/internal/zipreader.h +++ b/src/internal/zipreader.h @@ -5,10 +5,12 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { -class ZipReader +class LIBSCRATCHCPP_TEST_EXPORT ZipReader { public: ZipReader(const std::string &fileName); diff --git a/src/project_p.cpp b/src/project_p.cpp index bfc005ae5..20359165f 100644 --- a/src/project_p.cpp +++ b/src/project_p.cpp @@ -13,15 +13,13 @@ using namespace libscratchcpp; -IProjectDownloaderFactory *ProjectPrivate::downloaderFactory = nullptr; - ProjectPrivate::ProjectPrivate() : engine(std::make_shared()) { - if (!downloaderFactory) - downloaderFactory = ProjectDownloaderFactory::instance().get(); + if (!m_downloaderFactory) + m_downloaderFactory = ProjectDownloaderFactory::instance().get(); - downloader = downloaderFactory->create(); + downloader = m_downloaderFactory->create(); } ProjectPrivate::ProjectPrivate(const std::string &fileName) : @@ -194,3 +192,13 @@ sigslot::signal &ProjectPrivate::downloadProgressCha { return downloader->downloadProgressChanged(); } + +IProjectDownloaderFactory *ProjectPrivate::downloaderFactory() +{ + return m_downloaderFactory; +} + +void ProjectPrivate::setDownloaderFactory(IProjectDownloaderFactory *downloaderFactory) +{ + m_downloaderFactory = downloaderFactory; +} diff --git a/src/project_p.h b/src/project_p.h index cb937f3ae..1836ec603 100644 --- a/src/project_p.h +++ b/src/project_p.h @@ -5,6 +5,8 @@ #include #include +#include "test_export.h" + namespace libscratchcpp { @@ -13,8 +15,9 @@ class IProjectReader; class IProjectDownloaderFactory; class IProjectDownloader; -struct ProjectPrivate +class LIBSCRATCHCPP_TEST_EXPORT ProjectPrivate { + public: ProjectPrivate(); ProjectPrivate(const std::string &fileName); ProjectPrivate(const ProjectPrivate &) = delete; @@ -33,8 +36,13 @@ struct ProjectPrivate std::atomic stopLoading = false; std::shared_ptr engine = nullptr; - static IProjectDownloaderFactory *downloaderFactory; std::shared_ptr downloader; + + static IProjectDownloaderFactory *downloaderFactory(); + static void setDownloaderFactory(IProjectDownloaderFactory *downloaderFactory); + + private: + static inline IProjectDownloaderFactory *m_downloaderFactory = nullptr; }; }; // namespace libscratchcpp diff --git a/src/scratch/list_functions.cpp b/src/scratch/list_functions.cpp index 44586f623..fd2a694f0 100644 --- a/src/scratch/list_functions.cpp +++ b/src/scratch/list_functions.cpp @@ -8,57 +8,57 @@ using namespace libscratchcpp; extern "C" { - void list_clear(List *list) + LIBSCRATCHCPP_EXPORT void list_clear(List *list) { list->clear(); } - void list_remove(List *list, size_t index) + LIBSCRATCHCPP_EXPORT void list_remove(List *list, size_t index) { list->removeAt(index); } - ValueData *list_append_empty(List *list) + LIBSCRATCHCPP_EXPORT ValueData *list_append_empty(List *list) { return &list->appendEmpty(); } - ValueData *list_insert_empty(List *list, size_t index) + LIBSCRATCHCPP_EXPORT ValueData *list_insert_empty(List *list, size_t index) { return &list->insertEmpty(index); } - ValueData *list_get_item(List *list, size_t index) + LIBSCRATCHCPP_EXPORT ValueData *list_get_item(List *list, size_t index) { return &list->operator[](index); } - ValueData *list_data(List *list) + LIBSCRATCHCPP_EXPORT ValueData *list_data(List *list) { return list->data(); } - ValueData *const *list_data_ptr(List *list) + LIBSCRATCHCPP_EXPORT ValueData *const *list_data_ptr(List *list) { return list->dataPtr(); } - size_t *list_size_ptr(List *list) + LIBSCRATCHCPP_EXPORT size_t *list_size_ptr(List *list) { return list->sizePtr(); } - const size_t *list_alloc_size_ptr(List *list) + LIBSCRATCHCPP_EXPORT const size_t *list_alloc_size_ptr(List *list) { return list->allocatedSizePtr(); } - size_t list_size(List *list) + LIBSCRATCHCPP_EXPORT size_t list_size(List *list) { return list->size(); } - void list_to_string(List *list, StringPtr *dst) + LIBSCRATCHCPP_EXPORT void list_to_string(List *list, StringPtr *dst) { list->toStringPtr(dst); } diff --git a/src/scratch/sound_p.cpp b/src/scratch/sound_p.cpp index 85b354e08..8fca3f29c 100644 --- a/src/scratch/sound_p.cpp +++ b/src/scratch/sound_p.cpp @@ -5,13 +5,16 @@ using namespace libscratchcpp; -IAudioOutput *SoundPrivate::audioOutput = nullptr; - SoundPrivate::SoundPrivate() { // NOTE: audioOutput must be initialized in the constructor to avoid static initialization order fiasco - if (!audioOutput) - audioOutput = AudioOutput::instance().get(); + if (!m_audioOutput) + m_audioOutput = AudioOutput::instance().get(); + + player = m_audioOutput->createAudioPlayer(); +} - player = audioOutput->createAudioPlayer(); +void SoundPrivate::setAudioOutput(IAudioOutput *audioOutput) +{ + m_audioOutput = audioOutput; } diff --git a/src/scratch/sound_p.h b/src/scratch/sound_p.h index 83074bed2..63400798d 100644 --- a/src/scratch/sound_p.h +++ b/src/scratch/sound_p.h @@ -6,6 +6,7 @@ #include "audio/iaudiooutput.h" #include "audio/iaudioplayer.h" +#include "test_export.h" namespace libscratchcpp { @@ -13,17 +14,22 @@ namespace libscratchcpp class Sound; class Thread; -struct SoundPrivate +class LIBSCRATCHCPP_TEST_EXPORT SoundPrivate { + public: SoundPrivate(); SoundPrivate(const SoundPrivate &) = delete; int rate = 0; int sampleCount = 0; - static IAudioOutput *audioOutput; std::shared_ptr player = nullptr; const Sound *cloneRoot = nullptr; Thread *owner = nullptr; + + static void setAudioOutput(IAudioOutput *newAudioOutput); + + private: + static inline IAudioOutput *m_audioOutput = nullptr; }; } // namespace libscratchcpp diff --git a/src/scratch/value_functions.cpp b/src/scratch/value_functions.cpp index d913fd57d..5d4e7b441 100644 --- a/src/scratch/value_functions.cpp +++ b/src/scratch/value_functions.cpp @@ -15,7 +15,7 @@ extern "C" /* free */ /*! Frees memory used by the given value if it's a string. */ - void value_free(ValueData *v) + LIBSCRATCHCPP_EXPORT void value_free(ValueData *v) { if (v->type == ValueType::String) { assert(v->stringValue); @@ -27,7 +27,7 @@ extern "C" /* init */ /*! Initializes the given value. */ - void value_init(ValueData *v) + LIBSCRATCHCPP_EXPORT void value_init(ValueData *v) { v->type = ValueType::Number; v->numberValue = 0; @@ -36,7 +36,7 @@ extern "C" /* assign */ /*! Assigns number of type 'double' to the given value. */ - void value_assign_double(ValueData *v, double numberValue) + LIBSCRATCHCPP_EXPORT void value_assign_double(ValueData *v, double numberValue) { value_free(v); @@ -45,7 +45,7 @@ extern "C" } /*! Assigns boolean to the given value. */ - void value_assign_bool(ValueData *v, bool boolValue) + LIBSCRATCHCPP_EXPORT void value_assign_bool(ValueData *v, bool boolValue) { value_free(v); @@ -54,13 +54,13 @@ extern "C" } /*! Assigns string to the given value. */ - void value_assign_string(ValueData *v, const std::string &stringValue) + LIBSCRATCHCPP_EXPORT void value_assign_string(ValueData *v, const std::string &stringValue) { value_assign_cstring(v, stringValue.c_str()); } /*! Assigns C string to the given value. */ - void value_assign_cstring(ValueData *v, const char *stringValue) + LIBSCRATCHCPP_EXPORT void value_assign_cstring(ValueData *v, const char *stringValue) { if (v->type != ValueType::String) { v->stringValue = string_pool_new(); @@ -71,7 +71,7 @@ extern "C" } /*! Assigns string to the given value. */ - void value_assign_stringPtr(ValueData *v, const StringPtr *stringValue) + LIBSCRATCHCPP_EXPORT void value_assign_stringPtr(ValueData *v, const StringPtr *stringValue) { if (v->type != ValueType::String) { v->stringValue = string_pool_new(); @@ -82,7 +82,7 @@ extern "C" } /*! Assigns pointer to the given value. */ - void value_assign_pointer(ValueData *v, const void *pointerValue) + LIBSCRATCHCPP_EXPORT void value_assign_pointer(ValueData *v, const void *pointerValue) { value_free(v); @@ -91,7 +91,7 @@ extern "C" } /*! Assigns another value to the given value. */ - void value_assign_copy(ValueData *v, const libscratchcpp::ValueData *another) + LIBSCRATCHCPP_EXPORT void value_assign_copy(ValueData *v, const libscratchcpp::ValueData *another) { if (another->type == ValueType::Number) { value_free(v); @@ -118,7 +118,7 @@ extern "C" /* type checkers */ /*! Returns true if the given value is Infinity. */ - bool value_isInfinity(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isInfinity(const libscratchcpp::ValueData *v) { switch (v->type) { case ValueType::Number: @@ -131,7 +131,7 @@ extern "C" } /*! Returns true if the given value is -Infinity. */ - bool value_isNegativeInfinity(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isNegativeInfinity(const libscratchcpp::ValueData *v) { switch (v->type) { case ValueType::Number: @@ -144,7 +144,7 @@ extern "C" } /*! Returns true if the given value is NaN. */ - bool value_isNaN(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isNaN(const libscratchcpp::ValueData *v) { switch (v->type) { case ValueType::Number: @@ -157,13 +157,13 @@ extern "C" } /*! Returns true if the given value is a number. */ - bool value_isNumber(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isNumber(const libscratchcpp::ValueData *v) { return v->type == ValueType::Number; } /*! Returns true if the given value is a number or can be converted to a number. */ - bool value_isValidNumber(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isValidNumber(const libscratchcpp::ValueData *v) { if (value_isNaN(v)) return false; @@ -183,7 +183,7 @@ extern "C" } /*! Returns true if the given value represents a round integer. */ - bool value_isInt(const ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isInt(const ValueData *v) { // https://github.com/scratchfoundation/scratch-vm/blob/112989da0e7306eeb405a5c52616e41c2164af24/src/util/cast.js#L157-L181 switch (v->type) { @@ -204,19 +204,19 @@ extern "C" } /*! Returns true if the given value is a pointer. */ - bool value_isPointer(const ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isPointer(const ValueData *v) { return v->type == ValueType::Pointer; } /*! Returns true if the given value is a boolean. */ - bool value_isBool(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isBool(const libscratchcpp::ValueData *v) { return v->type == ValueType::Bool; } /*! Returns true if the given value is a string. */ - bool value_isString(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_isString(const libscratchcpp::ValueData *v) { return v->type == ValueType::String; } @@ -224,7 +224,7 @@ extern "C" /* conversion */ /*! Returns the long representation of the given value. */ - long value_toLong(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT long value_toLong(const libscratchcpp::ValueData *v) { if (v->type == ValueType::Number) { return std::isnan(v->numberValue) || std::isinf(v->numberValue) ? 0 : v->numberValue; @@ -237,7 +237,7 @@ extern "C" } /*! Returns the int representation of the given value. */ - int value_toInt(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT int value_toInt(const libscratchcpp::ValueData *v) { if (v->type == ValueType::Number) return std::isnan(v->numberValue) || std::isinf(v->numberValue) ? 0 : v->numberValue; @@ -250,7 +250,7 @@ extern "C" } /*! Returns the double representation of the given value. */ - double value_toDouble(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT double value_toDouble(const libscratchcpp::ValueData *v) { if (v->type == ValueType::Number) { return std::isnan(v->numberValue) ? 0 : v->numberValue; @@ -263,7 +263,7 @@ extern "C" } /*! Returns the boolean representation of the given value. */ - bool value_toBool(const libscratchcpp::ValueData *v) + LIBSCRATCHCPP_EXPORT bool value_toBool(const libscratchcpp::ValueData *v) { if (v->type == ValueType::Bool) { return v->boolValue; @@ -279,7 +279,7 @@ extern "C" } /*! Writes the string representation of the given value to dst. */ - void value_toString(const ValueData *v, std::string *dst) + LIBSCRATCHCPP_EXPORT void value_toString(const ValueData *v, std::string *dst) { StringPtr *str = string_pool_new(); value_toStringPtr(v, str); @@ -288,7 +288,7 @@ extern "C" } /*! Writes the string representation of the given value to dst. */ - void value_toStringPtr(const ValueData *v, StringPtr *dst) + LIBSCRATCHCPP_EXPORT void value_toStringPtr(const ValueData *v, StringPtr *dst) { if (v->type == ValueType::String) string_assign(dst, v->stringValue); @@ -302,7 +302,7 @@ extern "C" } /*! Writes the UTF-16 representation of the given value to dst. */ - void value_toUtf16(const libscratchcpp::ValueData *v, std::u16string *dst) + LIBSCRATCHCPP_EXPORT void value_toUtf16(const libscratchcpp::ValueData *v, std::u16string *dst) { StringPtr *str = string_pool_new(); value_toStringPtr(v, str); @@ -311,7 +311,7 @@ extern "C" } /*! Returns the RGBA quadruplet from the given color value. */ - Rgb value_toRgba(const ValueData *v) + LIBSCRATCHCPP_EXPORT Rgb value_toRgba(const ValueData *v) { // https://github.com/scratchfoundation/scratch-vm/blob/112989da0e7306eeb405a5c52616e41c2164af24/src/util/cast.js#L92-L103 StringPtr *string = nullptr; @@ -363,7 +363,7 @@ extern "C" } /*! Returns the pointer stored in the given value or nullptr if it isn't a pointer. */ - const void *value_toPointer(const ValueData *v) + LIBSCRATCHCPP_EXPORT const void *value_toPointer(const ValueData *v) { if (v->type == ValueType::Pointer) return v->pointerValue; @@ -372,7 +372,7 @@ extern "C" } /*! Returns true if the given number represents a round integer. */ - bool value_doubleIsInt(double v) + LIBSCRATCHCPP_EXPORT bool value_doubleIsInt(double v) { if (std::isinf(v) || std::isnan(v)) return true; @@ -383,7 +383,7 @@ extern "C" } /*! Converts the given number to string and stores the result in dst. */ - void value_doubleToStringPtr(double v, StringPtr *dst) + LIBSCRATCHCPP_EXPORT void value_doubleToStringPtr(double v, StringPtr *dst) { if (v == 0) string_assign_cstring(dst, "0"); @@ -458,13 +458,13 @@ extern "C" * Converts the given boolean to string. * \note Do not free the string! */ - const StringPtr *value_boolToStringPtr(bool v) + LIBSCRATCHCPP_EXPORT const StringPtr *value_boolToStringPtr(bool v) { return v ? &TRUE_STR : &FALSE_STR; } /*! Converts the given string to double. */ - double value_stringToDouble(const StringPtr *s) + LIBSCRATCHCPP_EXPORT double value_stringToDouble(const StringPtr *s) { if (strings_equal_case_sensitive(s, &INFINITY_STR)) return std::numeric_limits::infinity(); @@ -478,7 +478,7 @@ extern "C" * Converts the given string to double. * \param[out] ok Whether the conversion was successful. */ - double value_stringToDoubleWithCheck(const StringPtr *s, bool *ok) + LIBSCRATCHCPP_EXPORT double value_stringToDoubleWithCheck(const StringPtr *s, bool *ok) { *ok = true; @@ -491,7 +491,7 @@ extern "C" } /*! Converts the given string to boolean. */ - bool value_stringToBool(const StringPtr *s) + LIBSCRATCHCPP_EXPORT bool value_stringToBool(const StringPtr *s) { return s->size != 0 && !strings_equal_case_insensitive(s, &FALSE_STR) && !strings_equal_case_insensitive(s, &ZERO_STR); } @@ -499,31 +499,31 @@ extern "C" /* operations */ /*! Adds the given values and writes the result to dst. */ - void value_add(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) + LIBSCRATCHCPP_EXPORT void value_add(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { value_assign_double(dst, value_toDouble(v1) + value_toDouble(v2)); } /*! Subtracts the given values and writes the result to dst. */ - void value_subtract(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) + LIBSCRATCHCPP_EXPORT void value_subtract(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { value_assign_double(dst, value_toDouble(v1) - value_toDouble(v2)); } /*! Multiplies the given values and writes the result to dst. */ - void value_multiply(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) + LIBSCRATCHCPP_EXPORT void value_multiply(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { value_assign_double(dst, value_toDouble(v1) * value_toDouble(v2)); } /*! Divides the given values and writes the result to dst. */ - void value_divide(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) + LIBSCRATCHCPP_EXPORT void value_divide(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { value_assign_double(dst, value_toDouble(v1) / value_toDouble(v2)); } /*! Calculates the modulo the given values and writes the result to dst. */ - void value_mod(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) + LIBSCRATCHCPP_EXPORT void value_mod(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { const double a = value_toDouble(v1); const double b = value_toDouble(v2); @@ -533,19 +533,19 @@ extern "C" /* comparison */ /*! Returns true if the given values are equal. */ - bool value_equals(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2) + LIBSCRATCHCPP_EXPORT bool value_equals(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2) { return value_compare(v1, v2) == 0; } /*! Returns true if the first value is greater than the second value. */ - bool value_greater(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2) + LIBSCRATCHCPP_EXPORT bool value_greater(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2) { return value_compare(v1, v2) > 0; } /*! Returns true if the first value is lower than the second value. */ - bool value_lower(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2) + LIBSCRATCHCPP_EXPORT bool value_lower(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2) { return value_compare(v1, v2) < 0; } diff --git a/src/test_export.h b/src/test_export.h new file mode 100644 index 000000000..5e4a334e0 --- /dev/null +++ b/src/test_export.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef LIBSCRATCHCPP_TEST +#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#define LIBSCRATCHCPP_TEST_EXPORT __declspec(dllexport) +#else +#define LIBSCRATCHCPP_TEST_EXPORT __attribute__((visibility("default"))) +#endif +#else +#define LIBSCRATCHCPP_TEST_EXPORT +#endif diff --git a/test/assets/sound_test.cpp b/test/assets/sound_test.cpp index d87a65654..b9fd6bd04 100644 --- a/test/assets/sound_test.cpp +++ b/test/assets/sound_test.cpp @@ -18,11 +18,11 @@ class SoundTest : public testing::Test void SetUp() override { m_player = std::make_shared(); - SoundPrivate::audioOutput = &m_playerFactory; + SoundPrivate::setAudioOutput(&m_playerFactory); EXPECT_CALL(m_playerFactory, createAudioPlayer()).WillOnce(Return(m_player)); } - void TearDown() override { SoundPrivate::audioOutput = nullptr; } + void TearDown() override { SoundPrivate::setAudioOutput(nullptr); } AudioOutputMock m_playerFactory; std::shared_ptr m_player; @@ -170,8 +170,6 @@ TEST_F(SoundTest, IsPlaying) EXPECT_CALL(*m_player, isPlaying()).WillOnce(Return(false)); ASSERT_FALSE(sound.isPlaying()); - - SoundPrivate::audioOutput = nullptr; } TEST_F(SoundTest, Clone) diff --git a/test/blocks/event_blocks_test.cpp b/test/blocks/event_blocks_test.cpp index 299bd6803..275d7197b 100644 --- a/test/blocks/event_blocks_test.cpp +++ b/test/blocks/event_blocks_test.cpp @@ -264,7 +264,7 @@ TEST_F(EventBlocksTest, WhenGreaterThanPredicate) AudioInputMock audioInput; auto audioLoudness = std::make_shared(); - EventBlocks::audioInput = &audioInput; + EventBlocks::setAudioInput(&audioInput); EXPECT_CALL(audioInput, audioLoudness()).Times(3).WillRepeatedly(Return(audioLoudness)); EXPECT_CALL(*audioLoudness, getLoudness()).Times(3).WillRepeatedly(Return(23)); @@ -285,7 +285,7 @@ TEST_F(EventBlocksTest, WhenGreaterThanPredicate) ASSERT_EQ(thread.runPredicate(), retValues[i]); } - EventBlocks::audioInput = nullptr; + EventBlocks::setAudioInput(nullptr); TimerMock timer; EXPECT_CALL(m_engineMock, timer()).Times(3).WillRepeatedly(Return(&timer)); diff --git a/test/blocks/sensing_blocks_test.cpp b/test/blocks/sensing_blocks_test.cpp index 883056215..939cc8bb6 100644 --- a/test/blocks/sensing_blocks_test.cpp +++ b/test/blocks/sensing_blocks_test.cpp @@ -43,10 +43,10 @@ class SensingBlocksTest : public testing::Test registerBlocks(m_engine, m_extension.get()); m_audioLoudness = std::make_shared(); - SensingBlocks::audioInput = &m_audioInput; + SensingBlocks::setAudioInput(&m_audioInput); EXPECT_CALL(m_audioInput, audioLoudness()).WillRepeatedly(Return(m_audioLoudness)); - SensingBlocks::clock = &m_clock; + SensingBlocks::setClock(&m_clock); EXPECT_CALL(m_engineMock, targets()).WillRepeatedly(ReturnRef(m_engine->targets())); } @@ -54,8 +54,8 @@ class SensingBlocksTest : public testing::Test void TearDown() override { SensingBlocks::clearQuestions(); - SensingBlocks::audioInput = nullptr; - SensingBlocks::clock = nullptr; + SensingBlocks::setAudioInput(nullptr); + SensingBlocks::setClock(nullptr); } std::unique_ptr m_extension; diff --git a/test/blocks/sound_blocks_test.cpp b/test/blocks/sound_blocks_test.cpp index 482368b6d..442df3809 100644 --- a/test/blocks/sound_blocks_test.cpp +++ b/test/blocks/sound_blocks_test.cpp @@ -30,10 +30,10 @@ class SoundBlocksTest : public testing::Test m_extension->registerBlocks(m_engine); m_extension->onInit(m_engine); - SoundPrivate::audioOutput = &m_outputMock; + SoundPrivate::setAudioOutput(&m_outputMock); } - void TearDown() override { SoundPrivate::audioOutput = nullptr; } + void TearDown() override { SoundPrivate::setAudioOutput(nullptr); } std::unique_ptr m_extension; Project m_project; diff --git a/test/compiler/compiler_test.cpp b/test/compiler/compiler_test.cpp index 9cdbf44f4..dfb14143e 100644 --- a/test/compiler/compiler_test.cpp +++ b/test/compiler/compiler_test.cpp @@ -29,7 +29,7 @@ class CompilerTest : public testing::Test void SetUp() override { m_ctx = std::make_shared(&m_engine, &m_target); - CompilerPrivate::builderFactory = &m_builderFactory; + CompilerPrivate::setBuilderFactory(&m_builderFactory); EXPECT_CALL(m_builderFactory, createCtx(&m_engine, &m_target)).WillOnce(Return(m_ctx)); m_compiler = std::make_unique(&m_engine, &m_target); @@ -40,7 +40,7 @@ class CompilerTest : public testing::Test void TearDown() override { - CompilerPrivate::builderFactory = nullptr; + CompilerPrivate::setBuilderFactory(nullptr); m_builder.reset(); m_compareBlock.reset(); m_testVar.reset(); diff --git a/test/engine/engine_test.cpp b/test/engine/engine_test.cpp index 174ac50a3..66121708b 100644 --- a/test/engine/engine_test.cpp +++ b/test/engine/engine_test.cpp @@ -295,7 +295,7 @@ TEST(EngineTest, StopSounds) auto player1 = std::make_shared(); auto player2 = std::make_shared(); auto player3 = std::make_shared(); - SoundPrivate::audioOutput = &factory; + SoundPrivate::setAudioOutput(&factory); EXPECT_CALL(factory, createAudioPlayer()).WillOnce(Return(player1)).WillOnce(Return(player2)).WillOnce(Return(player3)); EXPECT_CALL(*player1, isLoaded).WillOnce(Return(false)); EXPECT_CALL(*player2, isLoaded).WillOnce(Return(false)); @@ -316,7 +316,7 @@ TEST(EngineTest, StopSounds) EXPECT_CALL(*player3, stop()); engine->stopSounds(); - SoundPrivate::audioOutput = nullptr; + SoundPrivate::setAudioOutput(nullptr); } TEST(EngineTest, GlobalVolume) diff --git a/test/load_project/load_project_test.cpp b/test/load_project/load_project_test.cpp index 4b9b86a78..f267fad91 100644 --- a/test/load_project/load_project_test.cpp +++ b/test/load_project/load_project_test.cpp @@ -81,12 +81,12 @@ TEST(LoadProjectTest, DownloadDefaultProject) { ProjectDownloaderFactoryMock factory; auto downloader = std::make_shared(); - ProjectPrivate::downloaderFactory = &factory; + ProjectPrivate::setDownloaderFactory(&factory); EXPECT_CALL(factory, create()).WillOnce(Return(downloader)); ProjectPrivate p; p.fileName = "https://scratch.mit.edu/projects/ABCDEFGH"; // NOTE: This is a fake URL - ProjectPrivate::downloaderFactory = nullptr; + ProjectPrivate::setDownloaderFactory(nullptr); std::string data = readFileStr("default_project.json"); static const std::vector assets = { @@ -144,12 +144,12 @@ TEST(LoadProjectTest, DownloadDefaultProjectFailure) { ProjectDownloaderFactoryMock factory; auto downloader = std::make_shared(); - ProjectPrivate::downloaderFactory = &factory; + ProjectPrivate::setDownloaderFactory(&factory); EXPECT_CALL(factory, create()).WillOnce(Return(downloader)); ProjectPrivate p; p.fileName = "https://scratch.mit.edu/projects/ABCDEFGH"; // NOTE: This is a fake URL - ProjectPrivate::downloaderFactory = nullptr; + ProjectPrivate::setDownloaderFactory(nullptr); std::string data = readFileStr("default_project.json"); static const std::vector assets = { diff --git a/test/project/project_test.cpp b/test/project/project_test.cpp index e11292381..c29619421 100644 --- a/test/project/project_test.cpp +++ b/test/project/project_test.cpp @@ -105,11 +105,11 @@ TEST(LoadProjectTest, DownloadProgressChanged) { ProjectDownloaderFactoryMock factory; auto downloader = std::make_shared(); - ProjectPrivate::downloaderFactory = &factory; + ProjectPrivate::setDownloaderFactory(&factory); EXPECT_CALL(factory, create()).WillOnce(Return(downloader)); ProjectPrivate p; - ProjectPrivate::downloaderFactory = nullptr; + ProjectPrivate::setDownloaderFactory(nullptr); sigslot::signal signal; EXPECT_CALL(*downloader, downloadProgressChanged).WillOnce(ReturnRef(signal)); @@ -120,11 +120,11 @@ TEST(LoadProjectTest, AbortDownload) { ProjectDownloaderFactoryMock factory; auto downloader = std::make_shared(); - ProjectPrivate::downloaderFactory = &factory; + ProjectPrivate::setDownloaderFactory(&factory); EXPECT_CALL(factory, create()).WillOnce(Return(downloader)); Project p; - ProjectPrivate::downloaderFactory = nullptr; + ProjectPrivate::setDownloaderFactory(nullptr); EXPECT_CALL(*downloader, cancel()); p.stopLoading(); diff --git a/test/scratch_classes/inputvalue_test.cpp b/test/scratch_classes/inputvalue_test.cpp index 5ea5f59d3..0a97fdd5a 100644 --- a/test/scratch_classes/inputvalue_test.cpp +++ b/test/scratch_classes/inputvalue_test.cpp @@ -119,14 +119,14 @@ TEST(InputValueTest, Compile) TargetMock target; CodeBuilderFactoryMock builderFactory; auto builder = std::make_shared(); - CompilerPrivate::builderFactory = &builderFactory; + CompilerPrivate::setBuilderFactory(&builderFactory); Compiler compiler(&engine, &target); auto block = std::make_shared("", ""); EXPECT_CALL(builderFactory, create).WillOnce(Return(builder)); EXPECT_CALL(*builder, build); compiler.compile(block.get()); - CompilerPrivate::builderFactory = nullptr; + CompilerPrivate::setBuilderFactory(nullptr); auto input = std::make_shared("", Input::Type::Shadow); input->setPrimaryValue(5); diff --git a/test/scratch_classes/target_test.cpp b/test/scratch_classes/target_test.cpp index 92596c012..cd982e088 100644 --- a/test/scratch_classes/target_test.cpp +++ b/test/scratch_classes/target_test.cpp @@ -446,7 +446,7 @@ TEST(TargetTest, Sounds) auto player1 = std::make_shared(); auto player2 = std::make_shared(); auto player3 = std::make_shared(); - SoundPrivate::audioOutput = &factory; + SoundPrivate::setAudioOutput(&factory); EXPECT_CALL(factory, createAudioPlayer()).WillOnce(Return(player1)).WillOnce(Return(player2)).WillOnce(Return(player3)); auto s1 = std::make_shared("sound1", "", "mp3"); auto s2 = std::make_shared("sound2", "", "wav"); @@ -477,7 +477,7 @@ TEST(TargetTest, Sounds) ASSERT_EQ(s2->target(), &target); ASSERT_EQ(s3->target(), &target); - SoundPrivate::audioOutput = nullptr; + SoundPrivate::setAudioOutput(nullptr); } TEST(TargetTest, Volume) @@ -501,7 +501,7 @@ TEST(TargetTest, Volume) auto player1 = std::make_shared(); auto player2 = std::make_shared(); auto player3 = std::make_shared(); - SoundPrivate::audioOutput = &factory; + SoundPrivate::setAudioOutput(&factory); EXPECT_CALL(factory, createAudioPlayer()).WillOnce(Return(player1)).WillOnce(Return(player2)).WillOnce(Return(player3)); auto s1 = std::make_shared("", "", ""); auto s2 = std::make_shared("", "", ""); @@ -531,7 +531,7 @@ TEST(TargetTest, Volume) EXPECT_CALL(*player3, setVolume(0)); target.setVolume(-0.5); - SoundPrivate::audioOutput = nullptr; + SoundPrivate::setAudioOutput(nullptr); } TEST(TargetTest, SoundEffects)