In this walkthrough article we’ll create a brand new C++ project in Visual Studio and make all the settings that are needed to use the EyeX C API. We’ll also touch on neighboring subjects such as how to get the EyeX components integrated into an automated build environment along the way.
This is our starting point: Visual Studio 2012, all empty and waiting for us.
Let’s not keep it waiting anymore: go File/New/Project.
Ok. What kind of project is this going to be? DirectX, Qt, OpenGL, or maybe GDI+? For now, let’s do the simplest thing possible: a console application.
Choose project type: Win32 Console Application, set the Name to SampleEyeXApp, and choose a suitable location where you want to place it. Then click OK.
Use the default values for everything in the wizard that appears and click Finish.
Let’s Build/Build Solution to make sure that everything is working. “Build succeeded” – fine. We now have a valid, working program that does absolutely nothing.
Referencing the EyeX header files
The next step is to include the header files and libraries from the EyeX SDK into the application. I’m assuming that you have downloaded and unpacked the EyeX SDK for C/C++ somewhere on your hard disk. Now we need to point out where those files are, so that the compiler and linker can find them.
There are several choices for referencing those files. For example:
- Create a Components/EyeX subdirectory within the project directory and copy the include and lib directories from the SDK into it. This makes it straightforward to reference its contents using relative paths. It also makes it easy to add the whole thing to source control – though you might prefer to keep binary components away from your source control system.
- Set up an environment variable that points to the SDK directory. The include and library paths can be specified relative to the SDK directory through this variable.
- Use absolute paths. This requires that all developer machines be set up in the same way. And if the path includes the version of the SDK, you will have to change it every time you upgrade the SDK.
For this walkthrough we are going to use absolute paths simply because, well, because this is a walkthough and not production software. Open the project properties dialog and select the C/C++ page. Now, before making any more changes, make sure that “All Configurations” is selected at the top of the dialog.
Enter the absolute path to the SDK directory followed by “\include” in the property field called “Additional Include Directories”.
We should now be able to include EyeX header files from our code. Close the property dialog and add the following line immediately after the
The EyeX client library has to be initialized before use. Add the following lines to the main function:
if (TX_RESULT_OK != txInitializeEyeX(TX_EYEXCOMPONENTOVERRIDEFLAG_NONE, NULL, NULL, NULL, NULL))
Referencing the EyeX client library
At this point, compilation should succeed without errors, but we expect linker errors because we have still to link with the EyeX client library. To do that, add the following line immediately below the include statements:
#pragma comment (lib, "Tobii.EyeX.Client.lib")
It’s also possible to specify the library as a linker option if you don’t like pragma declarations and/or if you use a non-Microsoft compiler/linker.
We will also have to set up a library path similar to the include path. Open the project properties dialog and select the Linker page. Select “All Configurations” again. Enter the absolute path to the SDK directory followed by “\lib\x86” in the property field called “Additional Library Directories”.
Note that this assumes that we only want to build the application for the x86 platform. But of course we want to build it for the x64 platform as well! So, let’s open the Configuration Manager and add x64 as a solution and project platform.
We also have to change the library path for the x64 platform since the one we set up points to the x86 libs. Set it to the SDK directory path followed by “\lib\x64” for the x64 platform.
Copying the Tobii.EyeX.Client.dll to the output directory
We’re almost done. The code should compile and link without errors… but it won’t run just yet. If you try running it at this point, the dynamic loader will complain:
The error message is exaggerating a bit because Tobii.EyeX.Client.dll isn’t really missing from the computer. It’s just not present in the same directory as the executable file we’re trying to run. Copy it from SDK\lib\x86 (or x64), and everything should work fine. There are several ways you can do that, for example:
- Copy it manually. Easy and fast, but every developer on the team will have to do it every time they start from a clean checkout.
- Add a custom build event using Visual Studio. For example, you can add the following command to be run after a successful build:
1copy /b /y C:\TobiiEyeXSdk-Cpp-1.0.4711\lib\x64\*.dll $(OutDir)
Note that you will have to set up different custom build events for 32- and 64-bit builds because you need the 64-bit dll for the 64-bit builds and vice versa. (That is, the last part of the path differs for the two platforms.)
- Add a custom build event using MSBuild, the build engine that Visual Studio is built on top of. This is how it’s done in the SDK sample apps. It’s a clean method that works nicely but the drawback is that it’s a bit “secret”, and that many developers are unfamiliar with the MSBuild environment. If you want to use this method, open any of the SDK code sample project files in a text editor and look for this section at the end of the file:
1345<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /><ImportGroup Label="ExtensionTargets"></ImportGroup></Project>
The file called CopyEyeXDllToOutputDirectory.targets is a MSBuild script that injects a target into the build process. You will want to add a similar import statement into your own project file. You might also want to modify the paths inside the MSBuild script to fit your build environment.
Choose any method you wish to get the dll’s into the output directory and run your program. At this point it should run without errors! It doesn’t do much, but at least it runs. Mission completed!
In the next post in this series we’ll make something more useful: reading gaze data from the eye tracker.
EDIT Sep 8, 2014: Updated code snippets for EyeX Engine version 0.10.0
EDIT Dec 4, 2014: Updated code snippets for EyeX Engine version 1.0