Skip to content
Nicholas Corgan edited this page Dec 3, 2022 · 13 revisions

Python bindings for SoapySDR

The Python bindings for SoapySDR give the user access to the complete C++ API in Python. Because most of the API calls are identical to the C++ API, users should refer to the C++ headers and Doxygen for documentation. However, some calls have changed because of language differences. We will go over these calls in the examples below.

Dependencies

The Python bindings require SWIG and Python development files. We chose to use SWIG because it greatly simplified the developer effort required. To install the Python bindings, simply provide these dependencies before building SoapySDR.

Debian/Ubuntu:

sudo apt-get install python-dev swig

Windows+MSVC:

Basic example

import SoapySDR
from SoapySDR import * #SOAPY_SDR_ constants
import numpy #use numpy for buffers

#enumerate devices
results = SoapySDR.Device.enumerate()
for result in results: print(result)

#create device instance
#args can be user defined or from the enumeration result
args = dict(driver="rtlsdr")
sdr = SoapySDR.Device(args)

#query device info
print(sdr.listAntennas(SOAPY_SDR_RX, 0))
print(sdr.listGains(SOAPY_SDR_RX, 0))
freqs = sdr.getFrequencyRange(SOAPY_SDR_RX, 0)
for freqRange in freqs: print(freqRange)

#apply settings
sdr.setSampleRate(SOAPY_SDR_RX, 0, 1e6)
sdr.setFrequency(SOAPY_SDR_RX, 0, 912.3e6)

#setup a stream (complex floats)
rxStream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32)
sdr.activateStream(rxStream) #start streaming

#create a re-usable buffer for rx samples
buff = numpy.array([0]*1024, numpy.complex64)

#receive some samples
for i in range(10):
    sr = sdr.readStream(rxStream, [buff], len(buff))
    print(sr.ret) #num samples or error code
    print(sr.flags) #flags set by receive operation
    print(sr.timeNs) #timestamp for receive buffer

#shutdown the stream
sdr.deactivateStream(rxStream) #stop streaming
sdr.closeStream(rxStream)

More examples

Differences from C++ API

Factory API

The Device::make() and Device::unmake() factory functions are not used in Python. Rather, the Device constructor directly calls into the make() factory, and the Device destructor directly calls into unmake() for cleanup. In addition, there are no associated thread-safety issues because the factory calls are protected by a Python mutex.

Stream API

The readStream() and writeStream() calls do not support C++'s return-by-reference. Therefore, any readback parameters are not passed into the associated calls. Rather, they are returned in the result object which contains the normal return code, output flags, and output timeNs.

Rather than a pointer array, the readStream() and writeStream() calls expect a list of numpy arrays for the receive and transmit buffers. Notice that both calls support multiple channels; they must have a list of buffers, one per channel. Also, be careful about data types. In the example the stream was configured for complex float32, and we use the corresponding numpy data type: numpy.complex64.

Clone this wiki locally