From 21caa9de48ec1da7862fe5912f4bd895127e0681 Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Fri, 26 Oct 2018 11:57:52 +0200 Subject: [PATCH 1/2] Slic3r was split to a Slic3r.dll / Slic3r.exe / Slic3r-console.exe / Slic3r-noconsole.exe on Windows. --- src/CMakeLists.txt | 39 ++++++++++++++++++++++++++----- src/libslic3r/GCode/WipeTower.hpp | 1 + src/slic3r.cpp | 27 ++++++++++++++++----- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dbc4ecd21..621bce4ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -57,12 +57,18 @@ add_subdirectory(slic3r) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/slic3r.rc.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/slic3r.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.manifest @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/osx/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY) -add_executable(slic3r slic3r.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc) -if(SLIC3R_GUI) - set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-gui") -else() - set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-console") -endif() +if (MSVC) + add_library(slic3r SHARED slic3r.cpp) +else () + add_executable(slic3r slic3r.cpp) +endif () +if (NOT MSVC) + if(SLIC3R_GUI) + set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-gui") + else() + set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-console") + endif() +endif () target_link_libraries(slic3r libslic3r) if (APPLE) @@ -113,6 +119,27 @@ if (SLIC3R_GUI) endif () endif () +# On Windows, a shim application is required to produce a console / non console version of the Slic3r application. +# Also the shim may load the Mesa software OpenGL renderer if the default renderer does not support OpenGL 2.0 and higher. +if (MSVC) + add_executable(slic3r_app_gui WIN32 slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc) + target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE -DSLIC3R_WRAPPER_GUI) + add_dependencies(slic3r_app_gui slic3r) + target_link_libraries(slic3r_app_gui "-lShell32.lib") + set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r") + + add_executable(slic3r_app_console slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc) + target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE -DSLIC3R_WRAPPER_NOGUI) + add_dependencies(slic3r_app_console slic3r) + set_target_properties(slic3r_app_console PROPERTIES OUTPUT_NAME "slic3r-console") + + add_executable(slic3r_app_noconsole WIN32 slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc) + target_compile_definitions(slic3r_app_noconsole PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE -DSLIC3R_WRAPPER_NOGUI) + add_dependencies(slic3r_app_noconsole slic3r) + target_link_libraries(slic3r_app_gui "-lShell32.lib") + set_target_properties(slic3r_app_noconsole PROPERTIES OUTPUT_NAME "slic3r-noconsole") +endif () + # Link the resources dir to where Slic3r GUI expects it if (MSVC) if (CMAKE_CONFIGURATION_TYPES) diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index 5cbbc1ca9..8ea3abd93 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_WipeTower_hpp_ #define slic3r_WipeTower_hpp_ +#include <math.h> #include <utility> #include <string> #include <vector> diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 03e337db5..cf86c40ed 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -42,14 +42,12 @@ using namespace Slic3r; /// utility function for displaying CLI usage void printUsage(); -using namespace Slic3r; - +#ifdef _MSC_VER +int slic3r_main_(int argc, char **argv) +#else int main(int argc, char **argv) +#endif { - // Convert arguments to UTF-8 (needed on Windows). argv then points to memory owned by a. - //FIXME On Windows, we want to receive the arguments as 16bit characters! - boost::nowide::args a(argc, argv); - { const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL"); if (loglevel != nullptr) { @@ -253,3 +251,20 @@ void printUsage() print_print_options(boost::nowide::cout); std::cout << "****\n"; } + +#ifdef _MSC_VER +extern "C" { + __declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv) + { + // Convert wchar_t arguments to UTF8. + std::vector<std::string> argv_narrow; + std::vector<char*> argv_ptrs(argc + 1, nullptr); + for (size_t i = 0; i < argc; ++ i) + argv_narrow.emplace_back(boost::nowide::narrow(argv[i])); + for (size_t i = 0; i < argc; ++ i) + argv_ptrs[i] = const_cast<char*>(argv_narrow[i].data()); + // Call the UTF8 main. + return slic3r_main_(argc, argv_ptrs.data()); + } +} +#endif /* _MSC_VER */ From cf18ba0bbdd2819604a282fd5a17c346b1368f7e Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Fri, 26 Oct 2018 12:07:25 +0200 Subject: [PATCH 2/2] Added a new file missing from the previous commit. --- src/slic3r_app_msvc.cpp | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/slic3r_app_msvc.cpp diff --git a/src/slic3r_app_msvc.cpp b/src/slic3r_app_msvc.cpp new file mode 100644 index 000000000..702e49b45 --- /dev/null +++ b/src/slic3r_app_msvc.cpp @@ -0,0 +1,79 @@ +// Why? +#define _WIN32_WINNT 0x0502 +// The standard Windows includes. +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include <Windows.h> +#include <shellapi.h> +#include <wchar.h> +// Let the NVIDIA and AMD know we want to use their graphics card +// on a dual graphics card system. +__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; + +#include <stdlib.h> +#include <stdio.h> + +#include <string> +#include <vector> + +typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv); + +#ifdef SLIC3R_WRAPPER_NOCONSOLE +int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpCmdLine, int nCmdShow) +{ + int argc; + wchar_t **argv = CommandLineToArgvW(lpCmdLine, &argc); +#else +int wmain(int argc, wchar_t **argv) +{ +#endif + wchar_t path_to_exe[MAX_PATH + 1] = { 0 }; + ::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH); + wchar_t drive[_MAX_DRIVE]; + wchar_t dir[_MAX_DIR]; + wchar_t fname[_MAX_FNAME]; + wchar_t ext[_MAX_EXT]; + _wsplitpath(path_to_exe, drive, dir, fname, ext); + _wmakepath(path_to_exe, drive, dir, nullptr, nullptr); + +// https://wiki.qt.io/Cross_compiling_Mesa_for_Windows +// http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/ + wchar_t path_to_mesa[MAX_PATH + 1] = { 0 }; + wcscpy(path_to_mesa, path_to_exe); + wcscat(path_to_mesa, L"mesa\\opengl32.dll"); + printf("Loading MESA OpenGL library: %S\n", path_to_mesa); + HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0); + if (hInstance_OpenGL == nullptr) { + printf("MESA OpenGL library was not loaded\n"); + } + + wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 }; +// wcscpy(path_to_slic3r, path_to_exe); + wcscat(path_to_slic3r, L"slic3r.dll"); + printf("Loading Slic3r library: %S\n", path_to_slic3r); + HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0); +// if (hInstance_OpenGL == nullptr || hInstance_Slic3r == nullptr) { + if (hInstance_Slic3r == nullptr) { + printf("slic3r.dll was not loaded\n"); + return -1; + } + + // resolve function address here + Slic3rMainFunc slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r, "slic3r_main"); + if (slic3r_main == nullptr) { + printf("could not locate the function slic3r_main in slic3r.dll\n"); + return -1; + } + + std::vector<wchar_t*> argv_extended; + argv_extended.emplace_back(argv[0]); +#ifdef SLIC3R_WRAPPER_GUI + std::wstring cmd_gui = L"--gui"; + argv_extended.emplace_back(const_cast<wchar_t*>(cmd_gui.data())); +#endif + for (int i = 1; i < argc; ++ i) + argv_extended.emplace_back(argv[i]); + argv_extended.emplace_back(nullptr); + return slic3r_main(argc, argv_extended.data()); +}