diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ba178d1..4c3e42be 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,8 +85,13 @@ endif()
# Additional files to add to main executables
if(APPLE)
set(MTS_DARWIN_STUB "${CMAKE_CURRENT_SOURCE_DIR}/src/mitsuba/darwin_stub.mm")
+ set(MTS_WINDOWS_STUB "")
+elseif(WIN32)
+ set(MTS_DARWIN_STUB "")
+ set(MTS_WINDOWS_STUB "${CMAKE_CURRENT_SOURCE_DIR}/data/windows/wmain_stub.cpp")
else()
set(MTS_DARWIN_STUB "")
+ set(MTS_WINDOWS_STUB "")
endif()
diff --git a/SConstruct b/SConstruct
index 44f5ef65..c881913a 100644
--- a/SConstruct
+++ b/SConstruct
@@ -6,9 +6,10 @@ import os
resources = []
plugins = []
stubs = []
+winstubs = []
Export('SCons', 'sys', 'os', 'glob', 'resources',
- 'plugins', 'stubs')
+ 'plugins', 'stubs', 'winstubs')
# Configure the build framework
env = SConscript('build/SConscript.configure')
@@ -18,6 +19,9 @@ Export('env')
if sys.platform == 'win32':
# Set an application icon on Windows
resources += [ env.RES('data/windows/mitsuba_res.rc') ]
+ # Convert the command line args from UTF-8 to UTF-16
+ winstubs += [os.path.abspath('data/windows/wmain_stub.cpp')]
+ Export('winstubs')
def build(scriptFile, exports = [], duplicate = 0):
dirname = '/'.join(os.path.dirname(scriptFile).split('/')[1:])
diff --git a/data/windows/wmain_stub.cpp b/data/windows/wmain_stub.cpp
new file mode 100644
index 00000000..3580bbad
--- /dev/null
+++ b/data/windows/wmain_stub.cpp
@@ -0,0 +1,110 @@
+/*
+ This file is part of Mitsuba, a physically based rendering system.
+
+ Copyright (c) 2007-2012 by Wenzel Jakob and others.
+
+ Mitsuba is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License Version 3
+ as published by the Free Software Foundation.
+
+ Mitsuba is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#if defined(__WINDOWS__)
+
+// Stub for generating UTF-8 command line arguments from wmain (UTF-16)
+#include
+
+extern int mts_main(int argc, char **argv);
+
+
+namespace {
+
+class ArgsUTF8 {
+public:
+ ArgsUTF8(int argc, wchar_t *wargv[]) :
+ m_argc(-1), m_argv(NULL), m_data(NULL)
+ {
+ if (argc > 0)
+ m_argc = argc;
+ else
+ return;
+
+ m_argv = new char*[argc];
+ int total = 0;
+
+ // Pass 1: get the lengths of each converted string an allocate data
+ for (int i = 0; i < argc; ++i) {
+ const int lenUtf8 = WideCharToMultiByte(CP_UTF8, 0,
+ wargv[i], -1, NULL, 0, NULL, NULL);
+ if (lenUtf8 != 0) {
+ total += lenUtf8;
+ m_argv[i] = reinterpret_cast(lenUtf8);
+ } else {
+ m_argc = i;
+ break;
+ }
+ }
+
+ if (m_argc < 1)
+ return;
+
+ m_data = new char[total];
+ int currOffset = 0;
+
+ // Pass 2: perform the conversion
+ for (int i = 0; i < m_argc; ++i) {
+ int lenUtf8 = reinterpret_cast(m_argv[i]);
+ m_argv[i] = m_data + currOffset;
+ lenUtf8 = WideCharToMultiByte(CP_UTF8, 0,
+ wargv[i], -1, m_argv[i], lenUtf8, NULL, NULL);
+ if (lenUtf8 != 0) {
+ currOffset += lenUtf8;
+ } else {
+ m_argc = i;
+ return;
+ }
+ }
+ }
+
+ ~ArgsUTF8() {
+ if (m_argv != NULL) {
+ delete [] m_argv;
+ }
+ if (m_data != NULL) {
+ delete [] m_data;
+ }
+ }
+
+ inline int argc() const {
+ return m_argc;
+ }
+
+ inline char** argv() const {
+ return m_argv;
+ }
+
+private:
+ int m_argc;
+ char** m_argv;
+ char* m_data;
+};
+
+} // namespace
+
+
+// MSDN Documentation:
+// http://msdn.microsoft.com/en-US/library/fzc2cy7w%28v=vs.110%29.aspx
+int wmain(int argc, wchar_t *wargv[], wchar_t *envp[]) {
+ ArgsUTF8 argsUTF8(argc, wargv);
+ return mts_main(argsUTF8.argc(), argsUTF8.argv());
+}
+
+#endif // __WINDOWS__
diff --git a/src/converter/CMakeLists.txt b/src/converter/CMakeLists.txt
index 1e8fd414..0bfabe44 100644
--- a/src/converter/CMakeLists.txt
+++ b/src/converter/CMakeLists.txt
@@ -25,5 +25,5 @@ target_link_libraries(mtsconverter_lib
${COLLADA_LIBRARIES} ${XERCES_LIBRARIES} ${OPENGL_glu_LIBRARY})
add_mts_exe(mtsimport mtsimport.cpp ${SRCS}
- ${MTS_DARWIN_STUB} LINK_LIBRARIES mtsconverter_lib
+ ${MTS_DARWIN_STUB} ${MTS_WINDOWS_STUB} LINK_LIBRARIES mtsconverter_lib
RES_DESCRIPTION "Mitsuba COLLADA 1.4 & Wavefront OBJ importer")
diff --git a/src/converter/SConscript b/src/converter/SConscript
index 626a9906..f7112e89 100644
--- a/src/converter/SConscript
+++ b/src/converter/SConscript
@@ -1,4 +1,4 @@
-Import('mainEnv', 'hasCollada', 'stubs')
+Import('mainEnv', 'hasCollada', 'stubs', 'winstubs')
converter_objects = []
@@ -18,7 +18,7 @@ if hasCollada:
colladaEnv.StaticObject('obj.cpp'),
colladaEnv.StaticObject('converter.cpp')
]
- colladaEnv.Program('mtsimport', stubs + ['mtsimport.cpp']
+ colladaEnv.Program('mtsimport', stubs + winstubs + ['mtsimport.cpp']
+ converter_objects)
Return('converter_objects')
diff --git a/src/converter/mtsimport.cpp b/src/converter/mtsimport.cpp
index ba3b74c3..f7d1ff31 100644
--- a/src/converter/mtsimport.cpp
+++ b/src/converter/mtsimport.cpp
@@ -241,7 +241,7 @@ int mts_main(int argc, char **argv) {
return retval;
}
-#if !defined(__OSX__)
+#if !defined(__OSX__) && !defined(__WINDOWS__)
int main(int argc, char **argv) {
return mts_main(argc, argv);
}
diff --git a/src/mitsuba/CMakeLists.txt b/src/mitsuba/CMakeLists.txt
index 36d6ca8b..6baf6e4d 100644
--- a/src/mitsuba/CMakeLists.txt
+++ b/src/mitsuba/CMakeLists.txt
@@ -5,9 +5,9 @@ endif()
include_directories(${XERCES_INCLUDE_DIRS})
-add_mts_exe(mtssrv mtssrv.cpp
+add_mts_exe(mtssrv mtssrv.cpp ${MTS_WINDOWS_STUB}
RES_DESCRIPTION "Mitsuba compute node application")
-add_mts_exe(mitsuba mitsuba.cpp
+add_mts_exe(mitsuba mitsuba.cpp ${MTS_WINDOWS_STUB}
RES_DESCRIPTION "Mitsuba command line interface frontend")
-add_mts_exe(mtsutil mtsutil.cpp ${MTS_DARWIN_STUB}
+add_mts_exe(mtsutil mtsutil.cpp ${MTS_DARWIN_STUB} ${MTS_WINDOWS_STUB}
RES_DESCRIPTION "Mitsuba utility launcher")
diff --git a/src/mitsuba/SConscript b/src/mitsuba/SConscript
index 9a2abd4d..82bffc2a 100644
--- a/src/mitsuba/SConscript
+++ b/src/mitsuba/SConscript
@@ -1,4 +1,4 @@
-Import('sys', 'env', 'hasCollada', 'stubs')
+Import('sys', 'env', 'hasCollada', 'stubs', 'winstubs')
# Create an environment with Xerces and OpenGL
mainEnv = env.Clone()
@@ -24,10 +24,10 @@ if sys.platform == 'darwin':
stubs += [mainEnv_osx.StaticObject('darwin_stub.mm')]
mainEnv.Append(LINKFLAGS=['-Xlinker', '-rpath', '-Xlinker', '@executable_path/../Frameworks'])
-mainEnv.Program('mtsutil', stubs + ['mtsutil.cpp'])
+mainEnv.Program('mtsutil', stubs + winstubs + ['mtsutil.cpp'])
# Build the command-line+GUI interface
-mainEnv.Program('mtssrv', ['mtssrv.cpp'])
-mainEnv.Program('mitsuba', ['mitsuba.cpp'])
+mainEnv.Program('mtssrv', winstubs + ['mtssrv.cpp'])
+mainEnv.Program('mitsuba', winstubs + ['mitsuba.cpp'])
Return('mainEnv')
diff --git a/src/mitsuba/mitsuba.cpp b/src/mitsuba/mitsuba.cpp
index f81fcebf..44a4c3c6 100644
--- a/src/mitsuba/mitsuba.cpp
+++ b/src/mitsuba/mitsuba.cpp
@@ -124,7 +124,7 @@ private:
int m_timeout;
};
-int mts_main(int argc, char **argv) {
+int mitsuba_app(int argc, char **argv) {
char optchar, *end_ptr = NULL;
try {
@@ -397,7 +397,7 @@ int mts_main(int argc, char **argv) {
return 0;
}
-int main(int argc, char **argv) {
+int mts_main(int argc, char **argv) {
/* Initialize the core framework */
Class::staticInitialization();
Object::staticInitialization();
@@ -426,7 +426,7 @@ int main(int argc, char **argv) {
setlocale(LC_NUMERIC, "C");
#endif
- int retval = mts_main(argc, argv);
+ int retval = mitsuba_app(argc, argv);
/* Shutdown the core framework */
SceneHandler::staticShutdown();
@@ -449,3 +449,9 @@ int main(int argc, char **argv) {
return retval;
}
+
+#if !defined(__WINDOWS__)
+int main(int argc, char **argv) {
+ return mts_main(argc, argv);
+}
+#endif
diff --git a/src/mitsuba/mtssrv.cpp b/src/mitsuba/mtssrv.cpp
index e9d57fa6..bb931ed6 100644
--- a/src/mitsuba/mtssrv.cpp
+++ b/src/mitsuba/mtssrv.cpp
@@ -90,7 +90,7 @@ void collect_zombies(int s) {
}
#endif
-int mts_main(int argc, char **argv) {
+int mtssrv(int argc, char **argv) {
char optchar, *end_ptr = NULL;
try {
@@ -382,7 +382,7 @@ int mts_main(int argc, char **argv) {
return 0;
}
-int main(int argc, char **argv) {
+int mts_main(int argc, char **argv) {
/* Initialize the core framework */
Class::staticInitialization();
Object::staticInitialization();
@@ -409,7 +409,7 @@ int main(int argc, char **argv) {
setlocale(LC_NUMERIC, "C");
#endif
- int retval = mts_main(argc, argv);
+ int retval = mtssrv(argc, argv);
/* Shutdown the core framework */
SHVector::staticShutdown();
@@ -432,3 +432,9 @@ int main(int argc, char **argv) {
return retval;
}
+
+#if !defined(__WINDOWS__)
+int main(int argc, char **argv) {
+ return mts_main(argc, argv);
+}
+#endif
diff --git a/src/mitsuba/mtsutil.cpp b/src/mitsuba/mtsutil.cpp
index 0bc79720..282355ce 100644
--- a/src/mitsuba/mtsutil.cpp
+++ b/src/mitsuba/mtsutil.cpp
@@ -435,10 +435,8 @@ int mts_main(int argc, char **argv) {
return retval;
}
-#if !defined(__OSX__)
+#if !defined(__OSX__) && !defined(__WINDOWS__)
int main(int argc, char **argv) {
return mts_main(argc, argv);
}
#endif
-
-