aboutsummaryrefslogtreecommitdiffstats
path: root/host/docs/c_api.dox
blob: b37b81aaeedf059fbf04232af5522f5c1d647c19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*! \page page_c_api UHD - C API

\tableofcontents

\section c_api_intro Introduction

Alongside its C++ API, UHD provides a C API wrapper for the
uhd::usrp::multi_usrp and uhd::usrp_clock::multi_usrp_clock classes, as well as
their associated classes and structs. Other important UHD functions are also
included in this API. To use this API, simply:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
#include <uhd.h>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

...and all UHD C-level structs and functions will be available to you. The
sections below give more detail on the key features of the C API.

Keep in mind that the C-API is a wrapper around the C++ API, so performance can
never exceed that of the C++ API.

\subsection c_api_philosophy API Philosophy

The C API was designed to mirror the C++ API as closely as possible. This means
that most API calls are mapped 1:1 from C++ to C, and the documentation for the
C++ API can still be useful and should be considered when using the C API.
For example, the uhd_usrp_set_rx_antenna() and
uhd::multi_usrp::set_rx_antenna() calls do the same thing under the hood, and
thus, if the behaviour of the C API call is unclear, consulting the
corresponding C++ API call documentation can be helpful.

There are some C++ concepts that don't map into C easily, though. Among those
are object storage, which is solved by using handles (see \ref c_api_handles)
and exceptions, which are translated into error codes (see \ref c_api_errorcode).

\subsection c_api_handles C-Level Handles

Most of the UHD classes that can be accessed on the C level are done so through handles,
which internally store the C++ representation and allow access to internal values
through helper functions.

All handles have associated *_make() and *_free() functions. After creating a handle, it must
be passed through its make() function before it can be used in your program. Before the program
terminates, you must pass the handle into its free() function, or your program will have a memory
leak. The example below shows the proper usage of an RX metadata handle over the course of its
lifetime, from instantiation to destruction.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
uhd_rx_metadata_handle md;
uhd_rx_metadata_make(&md);

// Streaming here puts useful information into metadata
time_t full_secs;
double frac_secs;
uhd_rx_metadata_time_spec(md, &full_secs, &frac_secs);

uhd_rx_metadata_free(&md);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Again, make sure to pass your handle into a make() function before using it, or you will
run into undefined behavior. Also be careful not to use the handle after passing it into
a free() function, or your program will segfault.

\subsection c_api_errorcode Error Codes

As C cannot handle C++ runtime exceptions, UHD's C wrapper functions catch all exceptions
and translate them into error codes, which are returned by each function. Any output variables
are passed in as pointers into the function, which will set them internally.

Each uhd::runtime_error has a corresponding ::uhd_error value. Separate error codes indicate
that a boost::exception or std::exception has been thrown, and any other exceptions are
indicated by a catch-all ::UHD_ERROR_UNKNOWN code.

All UHD C-level handles store the string representation of the last C++ exception thrown internally.
These handles have corresponding *_get_last_error() functions that will place the error string into a
supplied string buffer.

For example, if a USRP device's handle throws an exception internally, the following code can access
its error info:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
char err_msg[256];
uhd_usrp_handle usrp;
double gain;
// USRP configuration done here
uhd_error error_code = uhd_usrp_get_rx_gain(usrp, 0, "", &gain);
if(error_code){
    uhd_usrp_get_last_error(usrp, err_msg, 256);
    fprintf(stderr, "Error code %d: %s\n", error_code, err_msg);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

All error codes can be found in <uhd/error.h>.

\subsection c_api_examples Example Code

UHD provides two examples that demonstrate the typical use case of the C API: RX and TX streaming.
The <b>rx_samples_c</b> example is a simplified C version of <b>rx_samples_to_file</b>,
and the <b>tx_samples_c</b> example is a simplified C version of <b>tx_waveforms</b>. These examples
can be easily adapted or serve as a starting point for your own UHD C applications.

*/
// vim:ft=doxygen: