Skip to content

Commit 690ab5a

Browse files
sternmullpcercuei
authored andcommitted
Add C++ API
This adds a C++17 API to the library. Implemented as a single header without dependencies. It simplifies usage of the library when a modern C++ compiler is available. Signed-off-by: Tilman Blumhagen <[email protected]>
1 parent cf1c072 commit 690ab5a

File tree

11 files changed

+956
-12
lines changed

11 files changed

+956
-12
lines changed

CI/azure/ci-ubuntu.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ set -x
33
uname -a
44
echo "$PWD"
55
mkdir build && cd build
6-
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DWITH_HWMON=ON -DWITH_SERIAL_BACKEND=ON -DWITH_EXAMPLES=ON -DPYTHON_BINDINGS=ON -DENABLE_PACKAGING=ON -DCPACK_SYSTEM_NAME="${ARTIFACTNAME}"
6+
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DWITH_HWMON=ON -DWITH_SERIAL_BACKEND=ON -DWITH_EXAMPLES=ON -DCPP_BINDINGS=ON -DPYTHON_BINDINGS=ON -DENABLE_PACKAGING=ON -DCPACK_SYSTEM_NAME="${ARTIFACTNAME}"
77
make
88
make package

CMakeLists.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ endif()
225225
set(LIBIIO_CFILES backend.c channel.c device.c context.c buffer.c utilities.c scan.c sort.c)
226226
set(LIBIIO_HEADERS iio.h)
227227

228+
set(DOXYGEN_INPUT "${CMAKE_SOURCE_DIR}")
229+
set(DOXYGEN_STRIP_FROM_PATH "${CMAKE_SOURCE_DIR}")
230+
231+
if (CPP_BINDINGS)
232+
list(APPEND LIBIIO_HEADERS bindings/cpp/iiopp.h)
233+
set(DOXYGEN_ENABLED_SECTIONS CPP_BINDINGS)
234+
set(DOXYGEN_INPUT "${DOXYGEN_INPUT} ${CMAKE_SOURCE_DIR}/bindings/cpp/")
235+
set(DOXYGEN_STRIP_FROM_PATH "${CMAKE_SOURCE_DIR}/bindings/cpp/")
236+
set(DOXYGEN_CPP_EXAMPLE_PATH "${CMAKE_SOURCE_DIR}/bindings/cpp/examples")
237+
endif()
238+
228239
if(WITH_USB_BACKEND)
229240
list(APPEND LIBIIO_CFILES usb.c)
230241
list(APPEND LIBS_TO_LINK ${LIBUSB_LIBRARIES})
@@ -485,7 +496,7 @@ set_target_properties(iio PROPERTIES
485496
VERSION ${VERSION}
486497
SOVERSION ${LIBIIO_VERSION_MAJOR}
487498
FRAMEWORK ${OSX_FRAMEWORK}
488-
PUBLIC_HEADER ${LIBIIO_HEADERS}
499+
PUBLIC_HEADER "${LIBIIO_HEADERS}"
489500
C_STANDARD 99
490501
C_STANDARD_REQUIRED ON
491502
C_EXTENSIONS OFF
@@ -560,6 +571,7 @@ if(WITH_DOC)
560571
endif()
561572
endif()
562573

574+
option(CPP_BINDINGS "Install C++ bindings" OFF)
563575
option(CSHARP_BINDINGS "Install C# bindings" OFF)
564576
option(PYTHON_BINDINGS "Install Python bindings" OFF)
565577
add_subdirectory(bindings)

Doxyfile.in

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ FULL_PATH_NAMES = YES
160160
# will be relative from the directory where doxygen is started.
161161
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
162162

163-
STRIP_FROM_PATH =
163+
STRIP_FROM_PATH = @DOXYGEN_STRIP_FROM_PATH@
164164

165165
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
166166
# path mentioned in the documentation of a class, which tells the reader which
@@ -708,7 +708,7 @@ GENERATE_DEPRECATEDLIST= YES
708708
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
709709
# ... \endcond blocks.
710710

711-
ENABLED_SECTIONS =
711+
ENABLED_SECTIONS = @DOXYGEN_ENABLED_SECTIONS@
712712

713713
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
714714
# initial value of a variable or macro / define can have for it to appear in the
@@ -854,7 +854,7 @@ WARN_LOGFILE = @CMAKE_BINARY_DIR@/Dox_output_@PROJECT_NAME@
854854
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
855855
# Note: If this tag is empty the current directory is searched.
856856

857-
INPUT = @CMAKE_SOURCE_DIR@
857+
INPUT = @DOXYGEN_INPUT@
858858

859859
# This tag can be used to specify the character encoding of the source files
860860
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -939,7 +939,8 @@ EXCLUDE_SYMBOLS =
939939
# command).
940940

941941
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/tests \
942-
@CMAKE_SOURCE_DIR@/examples
942+
@CMAKE_SOURCE_DIR@/examples \
943+
@DOXYGEN_CPP_EXAMPLE_PATH@
943944

944945
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
945946
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -2208,7 +2209,7 @@ INCLUDE_FILE_PATTERNS =
22082209
# recursively expanded use the := operator instead of the = operator.
22092210
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
22102211

2211-
PREDEFINED =
2212+
PREDEFINED = DOXYGEN
22122213

22132214
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
22142215
# tag can be used to specify a list of macro names that should be expanded. The

README_BUILD.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Cmake Options | Default | Target | Description
4040
---------------------- | ------- | -------| ---------------------------------------------- |
4141
`BUILD_SHARED_LIBS` | ON | All | Build shared libraries |
4242
'COMPILE_WARNING_AS_ERROR' | OFF | All | Make all C warnings into errors |
43+
`CPP_BINDINGS` | OFF | All | Install C++ bindings (C++17 required for examples) |
4344
`PYTHON_BINDINGS` | OFF | All | Install PYTHON bindings |
4445
`WITH_TESTS` | ON | All | Build the test programs (iio-utils) |
4546
`WITH_EXAMPLES` | OFF | All | Build the example programs |
@@ -57,7 +58,6 @@ Cmake Options | Default | Target | Description
5758
`OSX_FRAMEWORK` | ON | Mac | OS X frameworks provide the interfaces you need to write software for Mac. |
5859
`OSX_PACKAGE` | ON | Mac | Create a OSX package for installation on local and other machines |
5960

60-
6161
Which backends the library supports is dependent on the build system, but can be overridden.
6262
(If cmake finds libusb, it will use it, unless turned off manually)
6363

@@ -102,7 +102,7 @@ Cmake Options | Default | Description |
102102
```shell
103103
analog@precision:~/libiio$ mkdir build
104104
analog@precision:~/libiio/build$ cd build
105-
analog@precision:~/libiio/build$ cmake ../ -DPYTHON_BINDINGS=ON
105+
analog@precision:~/libiio/build$ cmake ../ -DCPP_BINDINGS=ON -DPYTHON_BINDINGS=ON
106106
analog@precision:~/libiio/build$ make -j$(nproc)
107107
```
108108

azure-pipelines.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,23 +208,23 @@ stages:
208208
- script: |
209209
set -e
210210
mkdir build && cd build
211-
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DOSX_PACKAGE=ON -DPYTHON_BINDINGS=ON -DWITH_EXAMPLES=ON -DWITH_SERIAL_BACKEND=OFF -DWITH_ZSTD=OFF
211+
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DOSX_PACKAGE=ON -DCPP_BINDINGS=ON -DPYTHON_BINDINGS=ON -DWITH_EXAMPLES=ON -DWITH_SERIAL_BACKEND=OFF -DWITH_ZSTD=OFF
212212
make
213213
sudo make install
214214
cd ..
215215
displayName: 'Build'
216216
- script: |
217217
set -e
218218
mkdir build_tar && cd build_tar
219-
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DOSX_PACKAGE=OFF -DENABLE_PACKAGING=ON -DPYTHON_BINDINGS=ON -DWITH_SERIAL_BACKEND=OFF -DWITH_ZSTD=OFF -DCPACK_SYSTEM_NAME=${ARTIFACTNAME}
219+
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DOSX_PACKAGE=OFF -DENABLE_PACKAGING=ON -DCPP_BINDINGS=ON -DPYTHON_BINDINGS=ON -DWITH_SERIAL_BACKEND=OFF -DWITH_ZSTD=OFF -DCPACK_SYSTEM_NAME=${ARTIFACTNAME}
220220
make
221221
make package
222222
cd ..
223223
displayName: 'Build tar'
224224
- script: |
225225
set -e
226226
cd build
227-
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DPYTHON_BINDINGS=ON -DWITH_DOC=ON
227+
cmake .. -Werror=dev -DCOMPILE_WARNING_AS_ERROR=ON -DCPP_BINDINGS=ON -DPYTHON_BINDINGS=ON -DWITH_DOC=ON
228228
make
229229
cd ..
230230
displayName: 'Build With Doc'

bindings/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
if (CPP_BINDINGS)
2+
add_subdirectory(cpp)
3+
endif()
4+
15
if (CSHARP_BINDINGS)
26
add_subdirectory(csharp)
37
endif()

bindings/cpp/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cmake_minimum_required(VERSION 2.8.12)
2+
3+
project(iiopp-enum CXX)
4+
add_executable(iiopp-enum examples/iiopp-enum.cpp iiopp.h ${LIBIIO_RC})
5+
target_include_directories(iiopp-enum PRIVATE ./)
6+
set_target_properties(iiopp-enum PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
7+
target_link_libraries(iiopp-enum iio)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* libiio - C++ API usage
4+
*
5+
* This example libiio program shows the usage of the C++ API for enumerating
6+
* devices, channels and attributes.
7+
*
8+
* Copyright (c) 2023, DIFITEC GmbH
9+
* Author: Tilman Blumhagen <[email protected]>
10+
*/
11+
12+
#include <iiopp.h>
13+
14+
#include <iostream>
15+
#include <iomanip>
16+
17+
using namespace iiopp;
18+
using namespace std;
19+
20+
string get(IAttr const & att)
21+
{
22+
char value[1024] = {0}; // Flawfinder: ignore
23+
att.read(value, sizeof(value)); // Flawfinder: ignore
24+
return value;
25+
}
26+
27+
void enumerateIioEntities()
28+
{
29+
cout << boolalpha;
30+
31+
shared_ptr<Context> context = create_default_context();
32+
33+
for (Device device : *context)
34+
{
35+
cout << "Device:" << endl;
36+
cout << " id: " << quoted(string(device.id())) << endl;
37+
38+
cout << " name: ";
39+
if (auto name = device.name())
40+
cout << quoted(string(*name));
41+
cout << endl;
42+
43+
cout << " is trigger: " << device.is_trigger() << endl;
44+
45+
for (auto att : device.attrs)
46+
cout << " attribute " << att.name() << " = " << quoted(get(att)) << endl;
47+
48+
for (auto att : device.debug_attrs)
49+
cout << " debug attribute " << att.name() << " = " << quoted(get(att)) << endl;
50+
51+
for (auto att : device.buffer_attrs)
52+
cout << " buffer attribute " << att.name() << " = " << quoted(get(att)) << endl;
53+
54+
for (Channel channel : device)
55+
{
56+
cout << " Channel: " << channel.id() << endl;
57+
58+
cout << " name: ";
59+
if (auto name = channel.name())
60+
cout << quoted(string(*name));
61+
cout << endl;
62+
63+
cout << " is output: " << channel.is_output() << endl;
64+
cout << " is enabled: " << channel.is_enabled() << endl;
65+
66+
for (auto att : channel.attrs)
67+
cout << " attribute " << quoted(att.name().c_str()) << " = " << quoted(get(att)) << endl;
68+
}
69+
}
70+
71+
shared_ptr<ScanContext> scanCtx = create_scan_context({}, 0);
72+
shared_ptr<ScanContext::InfoList> infoList = scanCtx->info_list();
73+
74+
cout << "scan context info list:" << endl;
75+
for (ContextInfo info : *infoList)
76+
{
77+
cout << " uri: " << quoted(info.uri().c_str()) << endl;
78+
cout << " description: " << quoted(info.desciption().c_str()) << endl;
79+
}
80+
81+
cout << "scan block:" << endl;
82+
shared_ptr<ScanBlock> blk = create_scan_block({}, 0);
83+
for (ContextInfo info : *blk)
84+
{
85+
cout << " uri: " << quoted(info.uri().c_str()) << endl;
86+
cout << " description: " << quoted(info.desciption().c_str()) << endl;
87+
}
88+
}
89+
90+
int main(int argc, char ** argv)
91+
{
92+
try
93+
{
94+
enumerateIioEntities();
95+
}
96+
catch (std::exception & e)
97+
{
98+
cerr << "ERROR: " << e.what() << endl;
99+
return EXIT_FAILURE;
100+
}
101+
102+
return EXIT_SUCCESS;
103+
}

0 commit comments

Comments
 (0)