CameraSDK : C++

The following section describe how to setup a CMake project, that works for both Windows and Linux based operating systems. Further, the CMake project automatically downloads the newest SDK binaries.

Build & Runtime Prerequisites

Depending on the target platform, our SDK’s depends on different system libraries.

Windows

  • Windows 10 (x64)

  • CMake 3.13 or later

  • MSVC 2019 or later

On Windows CMake will output Visual Studio (*.vcxproj) project files. So, if you prefer to work in Visual Studio, you can do that.

Tip

Visual Studio 2019 actually include (optional) built-in support for working directly with CMake files. This means there is no need to output vcxproj files at all.

However, the way to configure projects and debug parameters are different from the approach used with normal Visual C++ projects.

You can add the optional CMake component from the Visual Studio Installer application.

Linux

  • Ubuntu 20.04 (Focal) or later

  • CMake 3.13 or later

  • Either: GCC 7.5 or later or Clang 10 or later

  • libpthread

  • libatomic (CameraSDK only)

  • libusb-1.0-0 (CameraSDK only and optional)

You can of course use older Ubuntu’s or other Linux distros. We use Ubuntu 20.04 here, because it has a later CMake than 3.13 built into its apt-get repositories.

Caution

Ubuntu 18.04 (Bionic Beaver) has a too old CMake (3.10) as part of its default apt-get repositories. If you wish to use Bionic, you must install CMake directly from its website.

We provide 3 different binary versions of our SDK libraries for Linux, compiled with these compilers:

AMD64

ARM64

GCC

7.5

8.2

Clang

10

N/A

You should use the same or a newer GCC or Clang version, to ensure the ABI’s are compatible.

Note

In contrast to our Windows releases, we provide only a Release build of our libraries on Linux. Since GCC / Clang allows linking between libraries built using Debug and Release configurations.

Setup Your Project

Create a project folder, and name it something like hello_world. This folder will contain the entire sample project - including the downloaded SDK libraries.

$ mkdir hello_world
$ cd hello_world

Source Code

Now, let us add some example code that calls the CameraSDK. Create a new (empty) text file called main.cpp. Open the file in your favorite text editor and insert this content:

#include <iostream>
#include <vector>
#include <P1Camera.hpp>

using namespace P1::CameraSdk;

using std::cout;
using std::endl;

int main(int argc, const char** argv)
{
    cout << "Probing for available USB cameras..." << endl;

    std::vector<CameraListElement> list = Camera::GetAvailableCameras();

    cout << "Found " << list.size() << " camera" << (list.size() == 1 ? "" : "s") << endl;
    for(auto cam : list)
    {
        cout << " * " << cam.mName << " (" << cam.mSerialNum << ")" << endl;
    }

    if (list.size() <= 0)
    {
        cout << "Could not find any USB cameras!" << endl;
        return 1;
    }

    return 0;
}

This source code will query for any USB connected Phase One cameras. The connected cameras are listed in the console, before the program exits.

Caution

On Linux: CameraSDK has a soft dependency on libusb. This means it will be used, if it is found. If not found, there will be no USB support and no cameras will be found.

This is a runtime dependency only! You do not have to link with libusb, when your build your CameraSDK based applications. CameraSDK will automatically look for libusb upon first interaction with USB.

CMake File

Still inside the hello_world directory, create a new text file called CMakeLists.txt and insert this content:

 1cmake_minimum_required(VERSION 3.13)
 2
 3# Add FetchContent functionality
 4include(FetchContent)
 5
 6project(P1SdkProject)
 7
 8# SDK Major version
 9set(SDK_MAJOR_VERSION "2")
10
11# System name (lower case)
12string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME_LC)
13
14# File format extension
15if(WIN32)
16set(SDK_PACKAGE_EXT ".zip")
17else()
18set(SDK_PACKAGE_EXT ".tgz")
19endif()
20
21# Account for ARM based linux systems
22if(NOT APPLE AND UNIX AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
23set(LINUX_ARCH "-arm64")
24else()
25set(LINUX_ARCH "")
26endif()
27
28# Setup CameraSDK Download
29FetchContent_Declare(CameraSDK 
30    URL https://developer.phaseone.com/sdk/releases/camerasdk/${SDK_MAJOR_VERSION}/p1camerasdk-${SYSTEM_NAME_LC}${LINUX_ARCH}${SDK_PACKAGE_EXT}
31    SOURCE_DIR CameraSDK
32)
33# Download CameraSDK for the current system
34message(STATUS "Downloading CameraSDK...")
35FetchContent_Populate(CameraSDK)
36find_package(CameraSDK CONFIG REQUIRED HINTS ${CMAKE_CURRENT_BINARY_DIR}/CameraSDK)
37
38# Setup ImageSDK Download
39FetchContent_Declare(ImageSDK 
40    URL https://developer.phaseone.com/sdk/releases/imagesdk/${SDK_MAJOR_VERSION}/p1imagesdk-${SYSTEM_NAME_LC}${LINUX_ARCH}${SDK_PACKAGE_EXT}
41    SOURCE_DIR ImageSDK
42)
43# Download ImageSDK for the current system
44message(STATUS "Downloading ImageSDK...")
45FetchContent_Populate(ImageSDK)
46find_package(ImageSDK CONFIG REQUIRED HINTS ${CMAKE_CURRENT_BINARY_DIR}/ImageSDK)
47
48## Add sample executable
49
50add_executable(hello_world main.cpp)
51
52## Link static with SDKs
53
54target_link_libraries(hello_world PRIVATE
55    CameraSDK::CameraSdkCppStatic
56    ImageSDK::ImageSdkCppStatic
57)

Download the file here

This is our CMake project file, that will automatically download the SDK libraries and handle compiler setup, like include directories, pre-defines and linker directives.

In short, everything above line 50 is downloading Camera- & ImageSDK and making them available to CMake. The file will work for Windows, Linux and Linux ARM64 systems.

Below line 50, we define our executable (called hello_world), and that it should link with static libraries for both Camera- & ImageSDK.

Note

The source code in hello_world does not use any ImageSDK functionality. We link with it here, just for demonstration purposes.

Build & Run

By CMake convention, we should create a new directory called build, inside our project folder. Therefore, cd into this new build directory, before running two cmake commands to configure CMake, and compile the project:

$ mkdir build
$ cd build
$ cmake ..
$ cmake --build .

The first cmake command tells CMake to generate a target build system project, from our CMakeLists.txt file. The second cmake command triggers CMake to build the project using that target build system.

Tip

On Windows the default target build system is Visual Studio projects. When you run cmake .. a .vcxproj is created for the executable in our project. Then the cmake --build command will trigger the MSBuild tool, to build the Visual Studio project.

On Linux the default target build system is Unix Makefiles. When cmake .. is run, Makefiles are created from your CMake project file. The second command cmake --build simply triggers the make command.

Lastly, let’s run the hello_world application. If you have a camera connected via USB, you should see something similar to this:

$ ./hello_world
Probing for available cameras...
Found 1 camera
* IQ4 150MP (JD012345)
$
PS> .\\Debug\\hello_world.exe
Probing for available cameras...
Found 1 camera
* IQ4 150MP (JD012345)
PS>

Notice, that the location of the executable file differs between the target build systems. Visual Studio likes to position the binary inside a directory named after the compile configuration.

Hint

On Linux: In case you have attached a camera to USB, and do not see any cameras listed:

  • Verify that you have setup UDEV rules for your user account, that allows access to USB.

  • Verify that you have installed libusb-1.0-0 APT package.

See more in the Linux Troubleshooting appendix.

Using Dynamic Linking

Let’s change our project to use the provided dynamic library files, instead of the static ones. This means we need to change our CMakeLists.txt file.

We need to modify the lines 55 and 56 in our CMakeLists.txt file:

target_link_libraries(hello_world PRIVATE
    CameraSDK::CameraSdkCpp
    ImageSDK::ImageSdkCpp
)

We simply remove the Static postfix from the two lines.

On Linux, we can now compile and run the executable with the dynamic linkage.

Copy to build directory

Note

On Windows we also need to make sure that the SDK’s DLL files is available to the executable at runtime. This means we must add a post-build step to copy them to the build directory. Luckily, CMake can help with that too.

On Linux CMake automatically builds our executable with an embedded RPATH, that points to the SDK library files inside the build tree. This will ensure the executable works without any copying of files, as long as it is run inside the development setup.

This step is needed only on Windows.

If we try to run our app, the dynamic linker will fail at runtime, since it cannot locate the SDK .dll files. Windows’ dynamic linker will look for DLL’s in the same directory as the running .exe file. This behavior is unique to Windows.

We must first copy these files to the build destination directory. Add the following lines to CMakeLists.txt, to the bottom of the file:

add_custom_command(TARGET hello_world POST_BUILD 
    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:CameraSDK::CameraSdkCpp> $<TARGET_FILE_DIR:hello_world>
    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:ImageSDK::ImageSdkCpp> $<TARGET_FILE_DIR:hello_world>
)

This effectively adds a post-build step to the build process, copying the needed DLL files to the build directory - if needed.

After setting up the post-build step, you can run the executable successfully again.