# DeviceAtlas C API and Windows #
A how-to guide to compile and run the DeviceAtlas C API in a Windows environment.
## Requirements ##
The following tools and libraries are required to build the C API.
- [Cygwin](https://www.cygwin.com/) OR [MinGW](https://sourceforge.net/projects/mingw-w64/)
- make
- GCC 4.2 or above / Visual Studio 2015 or above
- CMake >=2.8
- PCRE >=8.38 (minimum v8.21 for improved performance) or PCRE2 10.x (or above).
### Optional ###
- CURL
- OpenSSL or LibreSSL
- libzip
- zlib
### Setup ###
#### Choosing between Cygwin and MinGW ####
Either Cygwin or MinGW can be used to build the C API on Windows. The build
process is more straightforward using Cygwin but execution of the API requires
the cygwin1.dll file to be available via the PATH environment variable or from
the System32/SysWOW64 directory. Cygwin has the advantage that it offers all
the required build tools and also a pre-built PCRE/PCRE2 library removing the need
to also build it.
Building with MinGW requires some extra steps as it does not come bundled with
CMake and typically also involves building PCRE/PCRE2 too. Once built, the API will
run without any other DLL dependencies.
The following section describes setting up the build environment for both Cygwin
and MinGW.
#### Cygwin Setup ####
Download and install Cygwin. Please ensure that the Cygwin bin directory is
added to the Windows PATH environment variable.
Cygwin uses a GUI installer for choosing the packages to install. The following
packages are required to build the C API: cmake, make, gcc-core, gcc-g++,
libpcre-devel and libpcre1. These packages can be manually selected from the
Cygwin installation GUI. Alternatively, the following command can be run via
cmd.exe to select/install all the required dependencies in the Cygwin GUI:
```cmd
C:\path\to\cygwinsetup> setup-x86.exe -q -P cmake -P make -P gcc-core -P gcc-g++ -P libpcre-devel -P libpcre1
```
Note that the above command installs the required pre-built PCRE libraries so it
is _not_ necessary to also build and install PCRE.
**Important** - if the Cygwin bin directory is _not_ added to the Windows PATH
environment variable and the API is run outside of the Cygwin shell then Windows
may display an error like the following: "The program can't start because
cygwin1.dll is missing from your computer."
#### MinGW Setup ####
An alternative to Cygwin is MinGW. MinGW is more minimalist than Cygwin and does
not come with a pre-built PCRE library. Download and install
[MinGW-w64](https://sourceforge.net/projects/mingw-w64/) and [CMake](https://cmake.org/).
Please ensure that the bin directories for both MinGW and CMake are added to the
Windows PATH environment variable.
**Important** - There are multiple MinGW projects. The project [MinGW](http://mingw.org)
is quite dated and it is recommended to use [MinGW-w64](https://sourceforge.net/projects/mingw-w64/)
instead.
Most of the commands in MinGW are consistent with Cygwin except for 'make'.
Please use 'mingw32-make' instead.
When using CMake, the default generator is typically NMake and not MinGW. It is
important to specify MinGW as the generator to create the correct Makefiles.
This is achieved with the -G parameter when running CMake:
```
% cmake -G "MinGW Makefiles"
```
#### Visual Studio Setup ####
From the cmake configuration, it will generate the proper Visual Studio Solution,
automatically setting the proper generator, eventually clarifying the architecture
wished (e.g 32 bitson 64 bits target).
It is highly recommended to use a modern package manager
(e.g. [vcpkg](https://github.com/microsoft/vcpkg/releases), [conan](https://conan.io/downloads.html))
to be able to handle all necessary dependencies, for both 32 and 64 bits architectures.
Both DLL and LIB are built, the former needs to be accessible from the
Path environment var.
Note in debug mode, pdb symbols files are recommended to be in same folder
level as those libraries, dependencies and the api's.
For DLL builds, the API's are compatible with the 64 bit ASLR linker flag.
Note the overall performance might decrease depending on other factors.
```
% cmake -DPCRE_INCLUDE_DIR= -DCPRELIB=
(Optional)
[-DCURL_INCLUDE_DIR= -DCURL_LIBRARY=]
[-DOPENSSL_ROOT_DIR=]
[-DZLIB_INCLUDE_DIR= -DZLIB_LIBRARY=]
[-DZIP_INCLUDE_DIR= -DZIP_LIBRARY=]
```
Note a script for vcpkg is proposed within the ExtraTools/Win32 folder, provided all
dependencies have been installed beforehand.
```
% .\ExtraTools\Win32\createproject_vcpkg.bat
```
### PCRE/PCRE2 ###
The DeviceAtlas C API uses a highly optimized trie structure. However, some
operations also require the use of the PCRE regex library. PCRE is required to
build and run the C API.
It is recommended to use a pre-built PCRE/PCRE2 package. Cygwin provides a pre-built
PCRE/PCRE2 library but MinGW does not. There are third party pre-built PCRE/PCRE2 libraries
available for MinGW.
Depending on your settings the built PCRE DLL library would be located in
<Disk drive>:\Windows\\(SysWOW64|System32) or /usr/lib
**Important** - The PCRE for Windows library found at [PCRE for Windows package](http://gnuwin32.sourceforge.net/packages/pcre.htm)
is obsolete and should not be used.
#### Building PCRE/PCRE2 ####
If a pre-built PCRE/PCRE2 library is not available it can be built from source. The
source code is available from the [PCRE/PCRE2 FTP server](ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/).
The typical build process is as follows but please note differences when using
MinGW.
```cmd
C:\> cd
C:\path\to\pcre\> cmake -DNON_STANDARD_LIB_PREFIX=1
C:\path\to\pcre\> make
```
To build using MinGW:
```cmd
C:\> cd
C:\path\to\pcre\> cmake -G "MinGW Makefiles" -DNON_STANDARD_LIB_PREFIX=1 -DBUILD_SHARED_LIBS=1
C:\path\to\pcre\> mingw32-make
```
The above should produce a pcre.dll file. It is recommended to place this in the
Windows System32 or SysWOW64 directory.
## Building the DeviceAtlas C API ##
The process to build the DeviceAtlas C API is straightforward but there are
small differences if using Cygwin or MinGW.
### Building using Cygwin ###
The build process using Cygwin assumes that the pre-built PCRE package were
installed using the Cygwin installer.
Building the C API with Cygwin:
```cmd
C:\> cd
C:\path\to\c-api\> cmake .
C:\path\to\c-api\> make
```
The build process should have produced DeviceAtlas libraries (libda.dll, libda.dll.a)
and Carrier API libraries (libci.dll, libci.dll.a). The
execution of the API can be verified by trying some of the example applications.
See the examples section below.
In order for the DeviceAtlas and Carrier APIs provided examples to work, the produced
libraries (libda.dll, libci.dll) should be placed on the working path or copied to
the working folder.
```cmd
C:\path\to\c-api\> cp .\Src\libci.dll .\Src\libda.dll .\Examples
```
### Building using MinGW ###
The build process using MinGW assume that a custom PCRE library has been built
from source and that the resulting pcre.dll file has been placed in either the
System32 or SysWOW64 directory. Note that the path to the extracted PCRE archive
is required for the PCRE headers.
**Important** - Some versions of MinGW do not have the necessary functions to
build the examples bundled with the C API. The CMakeLists.txt file can be edited
to disable the compilation of the examples if MinGW cannot compile all the
examples. This can be achieved by commenting out the examples line:
```(line 32) #add_subdirectory(examples)```
Building the C API with MinGW:
```cmd
C:\> cd
C:\path\to\c-api\> cmake -G "MinGW Makefiles" -DPCRE_INCLUDE_DIR=C:\path\to\pcre
C:\path\to\c-api\> mingw32-make
```
The build process should have produced DeviceAtlas libraries (libda.dll, libda.dll.a)
and Carrier API libraries (libci.dll, libci.dll.a). The
execution of the API can be verified by trying some of the example applications.
See the examples section below. Note that example0 should be compatible with all
versions of MinGW.
In order for the DeviceAtlas and Carrier APIs provided examples to work, the produced
libraries (libda.dll, libci.dll) should be placed on the working path or copied to
the working folder.
```cmd
C:\path\to\c-api\> cp .\Src\libci.dll .\Src\libda.dll .\Examples
```
### Further considerations ###
For integration into other C or C++ applications the DeviceAtlas headers and
resulting library are required. For integration into a .NET application only the
libda.dll library file is required.
By default, cmake will look for the PCRE DLL in one of the standard locations
mentioned above. If the PCRE DLL is in a custom location the cmake variables
PCRE_INCLUDE_DIR and PCRELIB should be used when building DeviceAtlas. For example:
```cmd
% cmake -DPCRE_INCLUDE_DIR=/opt/local/include -DPCRELIB=/opt/local/lib/libpcre.dll.a
```
### Updating the API ###
Normally the PCRE library does not need to be rebuilt when updating the
DeviceAtlas C API and can be deployed across Win32 ABI compatible machines.
The steps outlined above are the same for building a new C API version.
## Examples ##
Examples can be found in the Examples subfolder of the C API package. Please
ensure the DeviceAtlas data file has been downloaded and extracted.
The following shows how to run an example using cmd.exe shell:
```cmd
C:\> cd \Examples\device\getproperties
C:\path\to\c\api> cmake . && make && ./main
e.g.
C:\path\to\c\api> .main ..\20200301.json "Mozilla/5.0 (Linux; Android 4.2.2; HTC One Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.92 Mobile Safari/537.36"
```
Please note that example 4 shows how to hot-swap the data file for minimal
impact when updating the data file.
## Integration with .NET technologies ##
The built API can be called from .NET code via the the [DllImport feature][1]
and the [P/Invoke mechanism][2] (compatible with Microsoft .NET, .NET Core and
Mono). The following functions need to be imported to have a minimum of
functionality:
- [da_init](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_ae6a83d2bee98adb88bf65dc0e8aa5579.html#ae6a83d2bee98adb88bf65dc0e8aa5579)
- [da_fini](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a447d58ebd472a2cb070d0c64666aaaf2.html#a447d58ebd472a2cb070d0c64666aaaf2)
- [da_atlas_header_evidence_id](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a019442ae3fde38aa28b254b21bf9e269.html#a019442ae3fde38aa28b254b21bf9e269)
- [da_atlas_compile](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_adcb1c8fec0ee9bf80ccaa4f289bcc204.html#adcb1c8fec0ee9bf80ccaa4f289bcc204)
- [da_atlas_open](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a2eb87ba7f137f2f541eb1087722af066.html#a2eb87ba7f137f2f541eb1087722af066)
- [da_atlas_close](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_aeb1e01f371623217f7a60625b078cc2f.html#aeb1e01f371623217f7a60625b078cc2f)
- [da_searchv](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a37b2349f4fddc3967e740304a706f621.html#a37b2349f4fddc3967e740304a706f621)
- [da_search](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a631d0feb27811b79aa1147f508711172.html#a631d0feb27811b79aa1147f508711172)
- [da_close](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a6f206c4d51ea77bf37c48170a609f94d.html#a6f206c4d51ea77bf37c48170a609f94d)
- [da_getpropstring](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_ae5902fa6e81257a7549d845a5c781910.html#ae5902fa6e81257a7549d845a5c781910)
- [da_getpropinteger](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a476aa987cf78c72941b9fefee6e55b10.html#a476aa987cf78c72941b9fefee6e55b10)
- [da_getpropboolean](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a2a4ae76b9d8f8bb018fb88e671e81828.html#a2a4ae76b9d8f8bb018fb88e671e81828)
- [da_getproptype](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a69f0a2059c442541cdfe75e5afceac63.html#a69f0a2059c442541cdfe75e5afceac63)
- [da_getpropname](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a9aa5c02de0e81aaa1dae0bf01b520947.html#a9aa5c02de0e81aaa1dae0bf01b520947)
- [da_getfirstprop](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a9179c4a47073592090f7639f1d3964fb.html#a9179c4a47073592090f7639f1d3964fb)
- [da_getnextprop](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a6ff9e48dcc53b7031e589b5ee2c4ad67.html#a6ff9e48dcc53b7031e589b5ee2c4ad67)
- [da_getpropcount](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a259737627eebea4cd418610d6ea8677d.html#a259737627eebea4cd418610d6ea8677d)
If logging of API errors is required, these functions are also necessary:
- [da_reporterror](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a89bb11ba0d89ed51f7852fd439ab5e54.html#a89bb11ba0d89ed51f7852fd439ab5e54)
- [da_seterrorfunc](https://docs.deviceatlas.com/apis/enterprise/c/2.1/ApiDocs/dac_8h_a957e72f600e612b09e326f8e86bb8d58.html#a957e72f600e612b09e326f8e86bb8d58)
[1]:https://msdn.microsoft.com/en-us/library/aa984739(v=vs.71).aspx
[2]:https://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx
**Important** - Care must be taken when casting between safe/unsafe code in .NET.
Various flat C types (mainly numeric or enum) are used widely in the API and can
be cast to their managed .NET types counterpart directly like da_evidence_id_t,
da_propid_t, even da_status_t, da_severity_t etc. Most of the structs used to
load the data in memory or for the detection might not be castable so it may be
necessary to wrap them separately. There is only one raw C pointer to carry over
the lifetime of the object owner which would need to be freed in the destructor.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ Copyright (c) DeviceAtlas Limited 2021. All Rights Reserved. _
https://deviceatlas.com