.NET bindings for libpostal
This project wraps the libpostal C library and provides a more natural .NET experience over the generic p/Invoke DllImport mechanism. It relies on SWIG to do the heavy lifting for auto-generating p/Invoke calls to platform-specific libraries.
Things to note:
- 64-bit OS only
- Supports Windows/MacOS/Linux
- For Windows it requires Universal C Runtime - this is present for Windows 10+ but needs to be installed manually for editions of Windows prior to 10
- Currently does not support ARM
- To use this library you need the libpostal trained data - that can't be included in the repo due to github repo file size limitations
For Windows, you need to ensure you have a bash shell available - Git for Windows includes one, WSL2 also has this ability etc.
- Open a terminal that supports bash in the root directory where you have cloned this repository
- Run
./install_libpostal_data.sh
, which will- Download the trained model data
- Unzip the file
- Copy the data to the two test projects, which include it as content in their csproj files
- Remove the downloaded zip file and extracted folder
Compiled native libraries for libpostal for Windows/MacOS/Linux with SWIG wrapper entry points are included in this repo. To build simply open the solution and build.
During build a nuget package is created and placed in /package-feed
LMGTech.DotNetPostal.Tests use a project reference to LMGTech.DotNetPostal - some trickery is required to allow the tests to load the native libraries on each supported runtime.
Note: This is only needed when libpostal is updated - normally not required to just build this repository if you're only adding features to DotNetPostal.
Follow the platform-specific native build instructions below.
In the following steps it's assumed that:
- You cloned the libpostal git repo into a folder located at
{libpostal-path}
- This repo is cloned into a folder located at
{dotnet-postal-path}
- Install the following packages
sudo apt-get install curl autoconf automake libtool pkg-config git
sudo apt-get install swig
- Open your preferred terminal at
{dotnet-postal-path}/swig
- Run
./generate_swig_files.sh {libpostal-path}
- e.g../generate_swig_files.sh ~/github/libpostal
- Creates a
{libpostal-path}/src/libpostal_wrap.c
wrapper C file - Generates C# p/Invoke code at
{dotnet-postal-path}/src/LMGTech.DotNetPostal/Generated
- Includes
libpostal_wrap.c
in{libpostal-path}/src/Makefile.am
to ensure it is built when building libpostal
- Creates a
- Follow the Linux build instructions for libpostal
- Note: You don't need to do the final step
make install
i.e. you don't need to install the library on the machine as we only need the shared library file - You need to make a note of the configured
--datadir
that you specified during the build of libpostal - this directory is configured as part of the libpostal build process and is auto-populated with ML model data during the libpostal build process
- Note: You don't need to do the final step
- Open your preferred terminal at
{dotnet-postal-path}/swig
- Run
./copy_libpostal_library.sh {libpostal-path}
- e.g../copy_libpostal_library.sh ~/github/libpostal
- Copies the relevant platform-specific shared library to the platform-specific area under
{dotnet-postal-path}/src/LMGTech.DotNetPostal/runtimes
- Copies the relevant platform-specific shared library to the platform-specific area under
- Copy the contents of the configured libpostal
--datadir
to the following places:/tests/LMGTech.DotNetPostal.Tests/libpostaldata/
/tests/LMGTech.DotNetPostal.NuGet.Tests/libpostaldata/
- Install Homebrew
- Install the following Homebrew packages
brew install curl autoconf automake libtool pkg-config
brew install swig
- Open your preferred terminal at
{dotnet-postal-path}/swig
- Run
./generate_swig_files.sh {libpostal-path}
- e.g../generate_swig_files.sh ~/github/libpostal
- Creates a
{libpostal-path}/src/libpostal_wrap.c
wrapper C file - Generates C# p/Invoke code at
{dotnet-postal-path}/src/LMGTech.DotNetPostal/Generated
- Includes
libpostal_wrap.c
in{libpostal-path}/src/Makefile.am
to ensure it is built when building libpostal
- Creates a
- Follow the Linux build instructions for libpostal
- Note: You don't need to do the final step
make install
i.e. you don't need to install the library on the machine as we only need the shared library file - You need to make a note of the configured
--datadir
that you specified during the build of libpostal - this directory is configured as part of the libpostal build process and is auto-populated with ML model data during the libpostal build process
- Note: You don't need to do the final step
- Open your preferred terminal at
{dotnet-postal-path}/swig
- Run
./copy_libpostal_library.sh {libpostal-path}
- e.g../copy_libpostal_library.sh ~/github/libpostal
- Copies the relevant platform-specific shared library to the platform-specific area under
{dotnet-postal-path}/src/LMGTech.DotNetPostal/runtimes
- Copies the relevant platform-specific shared library to the platform-specific area under
- Copy the contents of the configured libpostal
--datadir
to the following places:/tests/LMGTech.DotNetPostal.Tests/libpostaldata/
/tests/LMGTech.DotNetPostal.NuGet.Tests/libpostaldata/
- Install MSYS2
- Open MSYS2 by running
MSYS2 MSYS
from the Start menu (note that there a multiple options here so choose the correct one!) - Run the following to install common tools -
pacman -S autoconf automake curl git make libtool
- Close the
MSYS2 MSYS
terminal - Open MSYS2 by running
MSYS2 MinGW UCRT x64
from the Start menu (note we are now using UCRT!) - Install the following tools
- gcc:
pacman -S mingw-w64-ucrt-x86_64-gcc
- SWIG:
pacman -S mingw-w64-ucrt-x86_64-swig
- gcc:
- Open MSYS2 by running
MSYS2 MinGW UCRT x64
from the Start menu - Navigate to
{dotnet-postal-path}/swig
- Run
./generate_swig_files.sh {libpostal-path}
- e.g../generate_swig_files.sh ~/github/libpostal
- Creates a
{libpostal-path}/src/libpostal_wrap.c
wrapper C file - Generates C# p/Invoke code at
{dotnet-postal-path}/src/LMGTech.DotNetPostal/Generated
- Includes
libpostal_wrap.c
in{libpostal-path}/src/Makefile.am
to ensure it is built when building libpostal
- Creates a
- Follow the Windows build instructions for libpostal
- Note: You don't need to do the final step
make install
i.e. you don't need to install the library on the machine as we only need the DLL file - You need to make a note of the configured
--datadir
that you specified during the build of libpostal - this directory is configured as part of the libpostal build process and is auto-populated with ML model data during the libpostal build process
- Note: You don't need to do the final step
- Open an
MSYS2 MinGW UCRT x64
terminal at{dotnet-postal-path}/swig
- Run
./copy_libpostal_library.sh {libpostal-path}
- e.g../copy_libpostal_library.sh ~/github/libpostal
- Copies the relevant platform-specific shared library to the platform-specific area under
{dotnet-postal-path}/src/LMGTech.DotNetPostal/runtimes
- Copies the relevant platform-specific shared library to the platform-specific area under
- Copy the contents of the configured libpostal
--datadir
to the following places:/tests/LMGTech.DotNetPostal.Tests/libpostaldata/
/tests/LMGTech.DotNetPostal.NuGet.Tests/libpostaldata/
- https://docs.microsoft.com/en-us/dotnet/standard/native-interop/cross-platform
- https://www.msys2.org/ - tools for C/C++ native builds on Windows
- https://www.swig.org/ - generates a C wrapper around a native library and corresponding C# p/Invoke methods and classes to call this wrapper
- https://www.msys2.org/docs/environments/ - SWIG environments, especially why UCRT is preferred for Windows10+
- https://iamsorush.com/posts/cpp-csharp-swig/ - nice example of using SWIG with CMAKE
- https://olegtarasov.me/build-cross-platform-c-library/ - example cross-platform C library called from .NET
- https://itwenty.me/2020/07/understanding-dyld-executable_path-loader_path-and-rpath/ - how dynamic library loading works on MacOS
- https://jacobpan3g.github.io/2017/09/01/build-dylib-on-mac/ - Cheat sheet for dynamic lib adjustments on MacOS
- dotnet/sdk#10575