DevTools:CSharp Bindings on Windows

From CrossWire Bible Society
Jump to: navigation, search

The standard Sword distribution contains bindings for C#. These will not make and run on Windows using Visual Studio 2013. This is a tutorial on the steps needed to get things working on Windows. The goal is to be able to cross develop on either Windows or Linux using the same source code. After downloading the current version of Sword [1]:

  1. Set up Sword for windows according to these instructions:
    http://crosswire.org/wiki/Tutorial:Compiling_%26_Installing_SWORD_on_Windows
    Except, stop before making libsword.sln, you will need to make some changes before the project will build successfully.
  2. Open \sword\sword\lib\vcppmake\libsword.sln in VS2013. VS will want to convert the project; allow this.

  3. Open the project properties window

    1. Under the C/C++ tab General, edit additional include directories, change icu-sword to icu
    2. Under the Linker tab General, edit additional library directories
      Change libcurl-vc10-x86-release-static-ipv6-sspi-spnego-winssl/lib to
      libcurl-vc-x86-release-static-ipv6-sspi-spnego-winssl/lib
      Change icu-sword/lib to icu/lib

  4. In the Solution Explorer window, drag the file: sword\bindings\flatapi.cpp into the solution.

  5. Open flatapi.h

    1. Replace all ' * SWDLLEXPORT ' with ' SWDLLEXPORT * ' (without the quotes)
    2. Replace all ' ** SWDLLEXPORT ' with ' SWDLLEXPORT ** ' (without the quotes)

    3. If they do not exist, declare the following functions:

      SWHANDLE SWDLLEXPORT org_crosswire_sword_SWMgr_newWithPath(const char *thePath);
      void SWDLLEXPORT org_crosswire_sword_InstallMgr_delete(SWHANDLE hInstallMgr);
      
  6. Open flatapi.cpp

    1. Make the replacements as in step 5
    2. Change all ::clearModInfo to clearTheModInfo (remove the colons and rename)

    3. Change the declaration of clearModInfo in the unnamed namespace to clearTheModInfo

    4. Define the functions in 5.3 above if they do not exist:

      SWHANDLE SWDLLEXPORT org_crosswire_sword_SWMgr_newWithPath(const char *thePath) {
          SWConfig *sysConf = new SWConfig(thePath);
          return (SWHANDLE) new HandleSWMgr(new WebMgr(sysConf));
      }
      void SWDLLEXPORT org_crosswire_sword_InstallMgr_delete(SWHANDLE hInstallMgr) {
          HandleInstMgr *hinstmgr = (HandleInstMgr*)hInstallMgr;
          if (hinstmgr) delete hinstmgr;
      }
      
  7. At this point, libsword.sln should make without errors

  8. In the Sword distribution, there is a bindings directory having a csharp directory. In that directory, edit the file NativeMethods.cs:

    1. In the NativeMethods class the DLLNAME changes from libsword.so to libsword
    2. In the NativeMethods class change:

      [DllImport(DLLNAME)] to
      [DllImport(DLLNAME, CallingConvention=CallingConvention.Cdecl)]
      
  9. Put all of the dlls in the sword project where C# can find them. Quick and dirty is to copy them all to the bin directory for the executable you will build. You may need the following dlls (I don't yet know yet which dlls do what, so I've included them all from the Windows build of the Sword distribution. This list works, a lesser list may be sufficient.):

    icule53.dll		clucene-core.dll	        icudt53.dll		icuuc53.dll
    liblzma.dll		icuio53.dll			icuin53.dll		binding.dll
    icutu53.dll		iculx53.dll			clucene-shared.dll
    libsword.dll	        libbz2.dll
    
  10. Figure out where you want your data files and edit sword.conf to point to that directory. Also put sword.conf somewhere reasonable.
    Note that in getting everything located, the differences between Linux and Windows on environment variables and file locations became sufficiently complex that I found it easier to create a C# class to manage all that. That class is located at CSharp Environment Variables Class.

  11. In sword\bindings\csharp\examples edit LookupExample.cs

    using (var manager = new manager()) //changes to
    using (var manager = new manager(@"path to sword.conf"))