StarDict can be compiled and run in windows.

Building StarDict

Use MS Visual Studio 2010 SP1 on Windows7 to build StarDict.

GTK

You need to install developer packages into "msvc_2010\gtk" directory. Download All-in-one bundle gtk+-bundle_2.24.10-20120208_win32.zip at https://download.gnome.org/binaries/win32/gtk%2B/2.24/ .

Note. bundle gtk+-bundle_2.22.1-20101227_win32.zip You may notice the following warning when building StarDict:

zdll.lib(d000034.o) : warning LNK4078: multiple '.text' sections found with different attributes (E0300020)

The zdll library that comes with this bundle should be replaced. Try this http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/zlib-dev_1.2.5-1_win32.zip. Unpack it into "msvc_2008\gtk" directory overwritting all files.

Download libiconv-1.9.1.bin.woe32.zip at http://sourceforge.net/projects/gettext/files/. Extract them into "msvc_2010\gtk\".

You may need to download the gettext-tools-0.13.1.bin.woe32.zip file too!

libxml library

stardict-editor project depends on libxml library (http://xmlsoft.org/). If you plan to build only StarDict, you do not need this library.

To build stardict-editor with libxml2 library you have two options: you may use either prebuild libxml2 binaries by Igor Zlatković. or build libxml2 from source. With prebuild binaries you'll be only able to build release version of stardict-editor. If you build libxml library from source, you'll be able to build both Release and Debug versions of stardict-editor.

See http://www.zlatkovic.com/libxml.en.html for details about libxml2 library on Windows.

I. building with prebuild binaries

1. Download libxml2-*.win32.zip from ftp://ftp.zlatkovic.com/libxml/

2. Unpack into msvc_2010, you'll get a msvc_2010/libxml2-*.win32 folder.

3. Rename libxml2-*.win32 to libxml2.

4. Rename msvc_2010/libxml2/lib to msvc_2010/libxml2/lib.release

II. building libxml library from source

1. download libxml archive (for example libxml2-2.7.7.tar.gz) from ftp://xmlsoft.org/libxml2/

    Note, I recommend against libxml2-2.7.8.tar.gz, it seems to be broken. 

2. extract the archive into msvc_2008, rename msvc_2008\libxml2-* to msvc_2008\libxml2-src

3. Windows menu->All Programs->Microsoft Visual Studio 2008->Visual Studio Tools->Visual Studio 2008 Command Prompt

4. cd to msvc_2008\libxml2-src\win32 in the opened console window.

5. Run "cscript configure.js help" to get a listing of all the build options (for your information only).

6. Building release version with default options.

cscript configure.js include=../../gtk/include lib=../../gtk/lib
nmake /f Makefile.msvc

you may see multiple warning like:

c14n.c
c:\stardict\msvc_2008\libxml2-src\libxml.h(94) : warning C4005: 'LIBXML_STATIC' : macro redefinition
        command-line arguments : see previous definition of 'LIBXML_STATIC'

I think they can be ignored.

7. build results are in msvc_2008\libxml2-src\win32\bin.msvc

8. copy msvc_2008\libxml2-src\win32\bin.msvc\libxml2_a.lib to msvc_2008\libxml2\lib.release\libxml2_a.lib

9. remove msvc_2008\libxml2-src folder, than repeat step 2 to recreate this folder

10. buiding a debug version

cscript configure.js cruntime=/MDd include=../../gtk/include lib=../../gtk/lib
nmake /f Makefile.msvc

11. copy msvc_2008\libxml2-src\win32\bin.msvc\libxml2_a.lib to msvc_2008\libxml2\lib.debug\libxml2_a.lib

12. copy msvc_2008\libxml2-src\include to msvc\libxml2\include

stardict-editor project configuration for libxml

stardict-editor MS Visual C++ project is already configured to build with libxml2. You do not need to change settings unless you want a custom build.

stardict-editor links libxml statically. You need to adjust project settings as follows to build the project.

1. link with libxml2_a.lib library

2. define the following macros LIBXML_STATIC, LIBXSLT_STATIC, LIBEXSLT_STATIC and XMLSEC_STATIC in project settings. These macros must be globally defined!

3. libxml2 library and the project must use the same version of the c-runtime library. It may be multi-threaded vs. single-threaded, release vs. debug, linked statically or dynamically.

Building libsigc++

1. Download libsigc++ (https://download.gnome.org/sources/libsigc%2B%2B/), unpack it into msvc_2010 directory. You'll get a directory like "msvc_2010\libsigc++-2.4.1".

For libsigc++-2.10.7:
Read MSVC_NMake/README.txt
libsigc++-2.10.7 don't support Visual Studio 2010.

libsigc++-2.4.1 is recommended as works fine!
libsigc++-2.2.4.2 is recommended for Visual Studio 2008 SP1!

2. Rename it to "msvc_2010\libsigc++-src".

3. Build the libsigc++ project with MS Visual Studio 2010 SP1 (do Release and Debug builds).

For libsigc++-2.5.3:
libsigc++-2.5.3 is the last version that support Visual Studio 2010.
libsigc++-2.5.3/MSVC_Net2010/libsigc++2.sln
MS Visual Studio 2010 can't open it, MS Visual Studio 2010 SP1 is needed!
But MS Visual Studio 2010 SP1 still can't compile it!

4. Copy

    MSVC_Net2010\Win32\Release\sigc-vc100-2_0.lib, 
    MSVC_Net2010\Win32\Release\sigc-vc100-2_0.dll, 
    MSVC_Net2010\Win32\Debug\sigc-vc100-d-2_0.lib, 
    MSVC_Net2010\Win32\Debug\sigc-vc100-d-2_0.dll 

    into "msvc_2010\libsigc++\". 

libsigc++ have static link problem on vs2008 (?).

sapi-tts plugin

For sapi-tts plugin, you need to install Microsoft Speech SDK. Download SpeechSDK51.exe and speechsdk51LangPack.exe files. Install it into "C:\Program Files\Microsoft Speech SDK 5.1" (into "C:\Program Files (x86)\Microsoft Speech SDK 5.1" on x64 platform).

Fix these compile errors in sphelper.h (only for x86):

1. add to the top of the file to prevent many errors

 #pragma warning( disable : 4430 )
 #pragma warning( disable : 4996 )
 

2. line 2372

    replace 

         for (const WCHAR * psz = (const WCHAR *)lParam; *psz; psz++) {}
 

    with 

         const WCHAR * psz;
         for (psz = (const WCHAR *)lParam; *psz; psz++) {}
 

3. line 2560

    replace 

     SPPHONEID* pphoneId = dsPhoneId;
 

    with 

     SPPHONEID* pphoneId = (SPPHONEID*)((WCHAR *)dsPhoneId);
 

4. line 2634

    replace 

   pphoneId += wcslen(pphoneId) + 1;
 

    with 

     pphoneId += wcslen((const wchar_t *)pphoneId) + 1;
 

Fix these compile warnings in sphelper.h (only for x64):

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\sphelper.h

1. line 1194

    replace 

     if( ( ::GetVersionEx( &ver ) == TRUE ) && ( ver.dwMajorVersion >= 6 ) )
 

    with 

     if( ( ::GetVersionEx( &ver ) ) && ( ver.dwMajorVersion >= 6 ) )
 

Acrobat wordpick plugin

See stardict\src\win32\acrobat\readme.txt file.

Notes

For stardict_powerword_parsedata.cpp, you need to add a UTF-8 BOM in its head to fix the compile problem. Just use the notepad to open it then save.

For wordnet plugin files, they are the same:
partic.h
geom.h
newton.h
newton_env.h
newton.cpp
newton_env.cpp
partic.cpp
scene.cpp


dictdotcn-plugin have no use now as the server stopped service! It is not needed now!


There are two crash bug with vs2005 (and likely with vs2008, vs2010), which you need to notice.

1. Use stardict_g_fopen instead of g_fopen. See http://bugzilla.gnome.org/show_bug.cgi?id=476810

2. Use fprintf_s instead of fprintf, or it will crash. This is a little strange.

libintl.h redefines *printf functions to libintl_*printf functions. That may be the cause of the crash. printf outputs nothing with console attached. Use printf_s instead, or better g_print.

There are two builds in vs2008: Debug and Release, you should choose Release version if you plan to distribute the result, you should choose Debug version for debugging the project.

You should can compile and run stardict successfully now. You cannot start stardict.exe in place, since a special directory structure is needed.

Solution structure

The StarDict solution consists of the following projects:

    stardict (stardict.dll) - a GUI part of StarDict packed into a dynamic library
    stardict-loader (stardict.exe) - an executable file that starts StarDict
    stardict-lib (stardict.lib) - a static library containing a non-GUI part of StarDict
    textouthook and textoutspy (textouthook.dll and textoutspy.dll) - implement scan words feature
    plugins - plugins loaded by StarDict and extending it functionality
    tests - test for StarDict
    tools/stardict-editor (stardict-editor.exe) - a GUI application providing auxiliary tools
    acrobat-wordpick-plugin - Adobe Acrobat plugin for scan words feature 

Code of StarDict application is divided into a number of projects: stardict-lib, stardict, stardict-loader. stardict-lib mainly contains non-GUI code. It was put into a library in order to facilitate testing. The tests solution folder holds test projects, they normaly link the stardict-lib library. The GUI part of the code was put in the stardict project. The division into GUI and non-GUI parts is not strict. Feel free to move code from stardict to stardict-lib and back if needed. stardict and stardict-lib project contains almost all code of the application excluding plugins and auxiliary libraries. stardict-loader is a small project which primary job is to load the StarDict application. stardict-loader inspects OS environment, set up directories, set environment variables and finally loads stardict.dll. stardict-loader should have as few dependencies as possible, it must not depend on GTK for example. Now stardict-loader only uses C Runtime Library and Windows API functions. One of the tasks of stardict-loader is to find GTK directory and add to the dll load path, so stardict.dll can be successfully started. This project produces stardict-loader.exe executable file, it will be renamed to stardict.exe in release version. Configuring the project to output stardict.exe leads to debugging problems in Visual Studio.

Unicode

It's recommended to build Unicode (versus ANSI) version of StarDict. That's done by default. You need to define UNICODE macro in compiler command line to build Unicode version.

Build the installer

Grab and install NSIS: http://nsis.sourceforge.net/Download I was using the 2.46 version.

Use stardict-prepare-installer.js to build win32-install-dir directory structure. You must have all the required files in place before running the script. See comment at the head of the file for details of running the script.

Some of the required files cannot be created on Windows, you need Linux to prepare them.

1. Download gtk2-runtime-*.exe from http://sourceforge.net/projects/gtk-win and put it into stardict\redist.

2. Download Microsoft Visual C++ 2010 Redistributable Package and put into redist. The file is named vcredist_x86.exe.

https://sourceforge.net/projects/vcredist/files/vcredist_2010_sp1/

3. From %PROGDIR%\Microsoft Visual Studio 8\VC\Redist\x86, copy Microsoft.VC80.CRT to redist.

Double click the stardict-installer.nsi :) NSIS will build the installer.

Warning

The libraries for Visual Studio often are updated after a release. For example, this can occur when you install a service pack. Visual Studio SP1 installs new version of C Runtime library as well as other libraries. Redistributable files in %PROGDIR%\Microsoft Visual Studio 8\VC\Redist\x86 are updated too. However, by default Visual Studio still bind applications to the original release version of libraries available. That is, after installing SP1, application built with Visual Studio require the libraries that were originally installed with Visual Studio 2008! For details see "Redistributing an Application and Binding It to Specific Libraries" at http://msdn.microsoft.com/en-us/library/cc664727.aspx.

In practice that means that after installing SP1.

1. You should continue to use vcredist_x86.exe for Visual Studio 2008.

2. %PROGDIR%\Microsoft Visual Studio 8\VC\Redist\x86 folder now contains files that do not satisfy dependency requirements of produced applications. You need the pre-SP1 files.

Note

vcredist_x86.exe for Visual Studio 2008 is affected by an annoying bug. It extracts temporary files into the root of the drive and does not remove them.

You will see the following files in the root of the drive after executing vcredist_x86.exe:

eula.1028.txt
eula.1031.txt
eula.1033.txt
eula.1036.txt
eula.1040.txt
eula.1041.txt
eula.1042.txt
eula.2052.txt
eula.3082.txt
globdata.ini
install.exe
install.ini
install.res.1028.dll
install.res.1031.dll
install.res.1033.dll
install.res.1036.dll
install.res.1040.dll
install.res.1041.dll
install.res.1042.dll
install.res.2052.dll
install.res.3082.dll
VC_RED.cab
VC_RED.MSI
vcredist.bmp

This bug was fixed in vcredist_x86.exe for Visual Studio 2008 SP1 (vcredist_x86-sp1.exe for short). vcredist_x86-sp1.exe installs libraries required to run applications built with Visual Studio 2008 no-SP1. Thus we may safely use vcredist_x86-sp1.exe instead of vcredist_x86.exe. The only drawback of that replacement is extra space needed for new libraries that are not used, vcredist_x86-sp1.exe (4.0 MiB) is larger than vcredist_x86.exe (1.7 MiB).

Despite the extra space required I recommend to use vcredist_x86-sp1.exe.

Deploying Visual C++ library with StarDict.

StarDict application as well as related tools and DLLs depend upon Visual C++ libraries that must be installed on the target computer in order for application to start. The following libraries are needed: C Runtime Library, Standard C++ Library. They both are part of the Microsoft.VC80.CRT assembly.

There are two way to distribute Visual C++ DLLs.

1. Using Visual C++ Redistributable Package (VCRedist_x86.exe) to install libraries into global assembly cache. This methods requires administrative rights.

2. Installing Microsoft.VC80.CRT as a private assembly in application's folder.

Whenever possible we should install Visual C++ libraries into the native assembly cache (WinSxS folder). That makes the libraries available to all applications no matter where they are installed. In some cases we do not have administrative rights or we should not alter the target system as with the portable version of StarDict. We have to use the second method. Privite assembly are subject of restrictions. We are not free to choose the folder where the private assembly is placed into. That must either the application folder or a subfolder of it named after the assembly name. Of two variants a subfolder in StarDict folder seams the best one - no extra DLLs near stardict.exe. We may have a directory structure like this:

$INSTALLDIR\stardict.exe
$INSTALLDIR\stardict-editor.exe
$INSTALLDIR\sigc-vc90-2_0.dll
$INSTALLDIR\textouthook.dll
$INSTALLDIR\textoutspy.dll
...
$INSTALLDIR\Microsoft.VC90.CRT\Microsoft.VC90.CRT.manifest
$INSTALLDIR\Microsoft.VC90.CRT\msvcm90.dll
$INSTALLDIR\Microsoft.VC90.CRT\msvcp90.dll
$INSTALLDIR\Microsoft.VC90.CRT\msvcr90.dll
...

Having Microsoft.VC90.CRT installed this way, Visual C++ libraries will be successfully loaded by stardict.exe, stardict-editor.exe and other DLLs in the "$INSTALLDIR" folder, but not by stardict plugins residing in $INSTALLDIR\plugins folder. The reason for this is "Assembly Searching Sequence", see http://msdn.microsoft.com/en-us/library/aa374224(VS.85).aspx for more details.

There are a number of possibilites to make plugins load successfully.

1. Copy the Microsoft.VC90.CRT folder into plugins. That is we'll have two copies of the Microsoft.VC90.CRT assembly: the first in the $INSTALLDIR folder and the second in the $INSTALLDIR\plugins folder. This make StarDict to load two different copies of the C Runtime and Standard C++ Libraries. The first copy will be loaded by StarDict itself, and the second will be loaded by plugins, hopefully all plugins will share one copy of each library.

This solution is not acceptable for two reasons. 1) Multiple copies of the sample library in process address space, 2) extra disk space required to store two copies of the same file.

2. Link all plugins with C Runtime and Standard C++ libraries statically. In this case each plugin will have its own copy of the library. That is not acceptable again.

3. Move all plugins from the plugins folder directly to $INSTALLDIR. This clutters StarDict folder, but should work OK with a single copy of assembly.

4. Remove reference to Microsoft.VC90.CRT assembly out of plugin manifests. Since Microsoft.VC90.CRT is the only assembly in plugin minifests we can drop the manifest entirely. This make plugin use the copy of C Runtime and Standard C++ Libraries loaded by StarDict.exe. Plugins are only loaded by stardict.exe so we can be sure both libraries present in the process address space.

To disable embedding a manifest into a DLL follow these steps:

    In Visual Studio open project properties.
    In configuration select "All Configurations"
    Navigate to Configuration Properties -> Linker -> Manifest File in the tree on the left.
    Set "Generate Manifest" property to "No". 

StarDict Portable installer

To build StarDict Portable installer you need to install additional programs and components.

    Install PortableApps.com Platform. You need only Platform, but you may install any Suite if you want.
        Use "C:\PortableApps" as installation directory. You may use you other installation directory, but in that case you need to pass portinst parameter to stardict-prepare-install.js script. 
    Install PortableApps.com Installer
    Install FindProcDLL NSIS plug-in
        Download KillProcDll&FindProcDll.zip from http://nsis.sourceforge.net/FindProcDLL_plug-in
        Unpack the archive into "C:\Program Files\NSIS\Plugins" folder. The archive contains two DLLs: FindProcDLL.dll and KillProcDLL.dll. 

To build StarDict Portable installer, execute stardict-prepare-install.js with portable=yes parameter.

Debugging

For debug, use these codes:

 FILE *file;
 file=fopen("C:\\a.txt", "a+");
 fprintf(file, "a\n");
 fclose(file);
 

StarDict sends debug messages, warnings, errors to console. Windows GUI applications do not attach to a console by default, hence all the aforementioned messages go nowhere.

There are to ways to make the output visible. You may attach StarDict to a windows console or open a log window. Both release and debug versions of StarDict allow to use console, while the log window is only available in the debug version.

To open window console pass --message-level option with non-zero parameter. The parameter specifies the amount of output to produce. The larger the value, the more verbose output will be. See StarDict help for more details. The --help option opens console as well. It prints a usage message and exits the application.

If you start StarDict with a shortcut, a new console windows is opened. It is closed with the application. If you start StarDict in an existing console window, the program do not open a new window, but prints all output to the existing one. Opening a new console has the disadvantage that if the application crushs, the console window closes so quickly you cannot read the error message.

Windows console has a limitation, it cannot show all unicode characters. To overcome this limitation StarDict can show output in a log window. The log window has no problems with showing unicode characters, but it can not fully duplicate console output. StarDict can show output of g_debug, g_error, g_warning and the like, g_print, g_printf(?) functions. You'll not see output from printf in the log window, for example. To enable the log window, build StarDict with ENABLE_LOG_WINDOW macro symbol.

All that windows console stuff is not much reliable, if it does not work, retreat to printing into a file or to the log window.

Running StarDict on another computer.

You may encounter a problem running StarDict project compiled with VS 2008 on other computer not having VS 2008. You may see the following rather unclear error message "This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem." The error happens because StarDict application, plugin DLLs, hook DLLs are linked with CRT (C runtime library) dynamically and you may not have the appropriate version on that dll on the target computer.

If you build Release version of the project, you need to download and install Microsoft Visual C++ 2008 Redistributable Package (x86).

If you build Debug version of the project, you need a debug version of CRT which not redistributable. I see at least one reason why you may need to use the debug version of StarDict - to debug the project remotely. Microsoft prohibit do distribute the debug version of CRT, but I assume a developer may do that for debuging purpose. Anyway this how to install the debuging version of CRT onto the target machine.

1. In Visual Studio create new Setup Project, name it Setup-CRTDebug.

2. Right-click the project in the Solution Explorer, select Add -> Merge module.

3. In the file selection dialog select "C:\Program Files\Common Files\Merge Modules\Microsoft_VC80_DebugCRT_x86.msm".

4. Build the project.

5. You've created Setup-CRTDebug.msi setup file. Run it on the target machine. It installs debug version of CRT. In the course of executing you'll be asked to specify an installation directory somewhere under "C:\Program Files". Never mind. The installer does not copy anything there. It does not even create that folder.

6. Now you should be able to start StarDict.

StarDict version

StarDict version for MSVC build can be specified in the msvc_2008\stardictrc.rc.

Two copies of CRT

When StarDict is build with MS Visual Studio, the resulting application has two copies (maybe more) of C Runtime library. The first copy comes with GTK+ libraries, the second is supplied by Visual Studio. The C Runtime library from Visual Studio resides in msvcr90.dll, that is a part of Microsoft.VC90.CRT assembly. Where is C Runtime Library that comes with GTK+ library, I do not know, but it surely can not be in msvcr90.dll. Having two copies of the library is a headache. There are two copies of environment variables. Setting an environment variable with function from one library, does not make that variable set in the other library. For example,

_wputenv(L"LANG=ru") - sets LANG variable to ru in MS C Runtime Library

g_getenv("LANG") - returns the value of the LANG variable in GTK+ C Runtime Library.

This may be any value, wputenv does not change the environment variable in GTK+ C Runtime Library.

We may live with two copies of the library pretty fine aside from special cases. In particular we need to synchronize LANG environment variable. StarDict Loader sets LANG environment variable to customize GUI interface. It specifies the language to use in interface. StarDict loader defines LANG variable in MS CRT only, the GTK+ CRT is not available yet. If we do nothing about the environment variable LANG in GTK+ CRT library, gettext library will use the default language for user interface. In order for StarDict loader to influence the GUI translation we must set the LANG variable in the GTK+ CRT too.

Notes

StarDict's win32 port got many experience from ReciteWord (my another project, http://reciteword.sourceforge.net) and Pidgin: http://www.pidgin.im

Note: when use fopen(), use "rb", never "r" (unless you know what you are doing).

Hu Zheng <huzheng001@gmail.com> http://www.huzheng.org

2022.1.12
