Add C++ bindings.
This commit is contained in:
parent
00ebcbf48a
commit
c23c8659b8
|
@ -43,6 +43,11 @@ Makefile.in
|
|||
# KDevelop project files
|
||||
*.kdev4
|
||||
|
||||
# Files generated by building C++ bindings
|
||||
bindings/cxx/libsigrok.xml
|
||||
bindings/cxx/include/libsigrok/enums.hpp
|
||||
bindings/cxx/enums.cpp
|
||||
|
||||
# Files generated by building Python bindings
|
||||
bindings/python/dist/
|
||||
bindings/python/build
|
||||
|
|
27
Makefile.am
27
Makefile.am
|
@ -379,6 +379,33 @@ tests_check_main_LDADD = $(top_builddir)/libsigrok.la @check_LIBS@
|
|||
|
||||
endif
|
||||
|
||||
if BINDINGS_CXX
|
||||
|
||||
lib_LTLIBRARIES += bindings/cxx/libsigrokxx.la
|
||||
|
||||
bindings_cxx_libsigrokxx_la_SOURCES = bindings/cxx/classes.cpp
|
||||
|
||||
bindings_cxx_libsigrokxx_la_LIBADD = -lsigrok $(glibmm_LIBS)
|
||||
|
||||
bindings_cxx_libsigrokxx_la_LDFLAGS = $(SR_LIB_LDFLAGS)
|
||||
|
||||
library_include_HEADERS += \
|
||||
bindings/cxx/include/libsigrok/libsigrok.hpp \
|
||||
bindings/cxx/include/libsigrok/enums.hpp
|
||||
|
||||
pkgconfig_DATA += bindings/cxx/libsigrokxx.pc
|
||||
|
||||
bindings/cxx/classes.lo: bindings/cxx/enums.cpp
|
||||
|
||||
bindings/cxx/enums.cpp: bindings/cxx/enums.py bindings/cxx/libsigrok.xml \
|
||||
bindings/cxx/ConfigKey_methods.cpp bindings/cxx/QuantityFlag_methods.cpp
|
||||
python $<
|
||||
|
||||
bindings/cxx/libsigrok.xml: include/libsigrok/libsigrok.h
|
||||
gccxml $(CFLAGS) -DGLIB_DISABLE_DEPRECATION_WARNINGS $< -fxml=$@
|
||||
|
||||
endif
|
||||
|
||||
MAINTAINERCLEANFILES = ChangeLog
|
||||
|
||||
.PHONY: ChangeLog
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
const DataType *ConfigKey::get_data_type() const
|
||||
{
|
||||
const struct sr_config_info *info = sr_config_info_get(id);
|
||||
if (!info)
|
||||
throw Error(SR_ERR_NA);
|
||||
return DataType::get(info->datatype);
|
||||
}
|
||||
|
||||
string ConfigKey::get_identifier() const
|
||||
{
|
||||
const struct sr_config_info *info = sr_config_info_get(id);
|
||||
if (!info)
|
||||
throw Error(SR_ERR_NA);
|
||||
return valid_string(info->id);
|
||||
}
|
||||
|
||||
string ConfigKey::get_description() const
|
||||
{
|
||||
const struct sr_config_info *info = sr_config_info_get(id);
|
||||
if (!info)
|
||||
throw Error(SR_ERR_NA);
|
||||
return valid_string(info->name);
|
||||
}
|
||||
|
||||
const ConfigKey *ConfigKey::get(string identifier)
|
||||
{
|
||||
const struct sr_config_info *info = sr_config_info_name_get(identifier.c_str());
|
||||
if (!info)
|
||||
throw Error(SR_ERR_ARG);
|
||||
return get(info->key);
|
||||
}
|
||||
|
||||
Glib::VariantBase ConfigKey::parse_string(string value) const
|
||||
{
|
||||
GVariant *variant;
|
||||
uint64_t p, q;
|
||||
|
||||
switch (get_data_type()->get_id())
|
||||
{
|
||||
case SR_T_UINT64:
|
||||
check(sr_parse_sizestring(value.c_str(), &p));
|
||||
variant = g_variant_new_uint64(p);
|
||||
break;
|
||||
case SR_T_STRING:
|
||||
variant = g_variant_new_string(value.c_str());
|
||||
break;
|
||||
case SR_T_BOOL:
|
||||
variant = g_variant_new_boolean(sr_parse_boolstring(value.c_str()));
|
||||
break;
|
||||
case SR_T_FLOAT:
|
||||
variant = g_variant_new_double(stod(value));
|
||||
break;
|
||||
case SR_T_RATIONAL_PERIOD:
|
||||
check(sr_parse_period(value.c_str(), &p, &q));
|
||||
variant = g_variant_new("(tt)", p, q);
|
||||
break;
|
||||
case SR_T_RATIONAL_VOLT:
|
||||
check(sr_parse_voltage(value.c_str(), &p, &q));
|
||||
variant = g_variant_new("(tt)", p, q);
|
||||
break;
|
||||
case SR_T_INT32:
|
||||
variant = g_variant_new_int32(stoi(value));
|
||||
break;
|
||||
default:
|
||||
throw Error(SR_ERR_BUG);
|
||||
}
|
||||
|
||||
return Glib::VariantBase(variant, true);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
const DataType *get_data_type() const;
|
||||
string get_identifier() const;
|
||||
string get_description() const;
|
||||
static const ConfigKey *get(string identifier);
|
||||
Glib::VariantBase parse_string(string value) const;
|
|
@ -0,0 +1,13 @@
|
|||
vector<const QuantityFlag *>
|
||||
QuantityFlag::flags_from_mask(unsigned int mask)
|
||||
{
|
||||
auto result = vector<const QuantityFlag *>();
|
||||
while (mask)
|
||||
{
|
||||
unsigned int new_mask = mask & (mask - 1);
|
||||
result.push_back(QuantityFlag::get(
|
||||
static_cast<enum sr_mqflag>(mask ^ new_mask)));
|
||||
mask = new_mask;
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
static vector<const QuantityFlag *>
|
||||
flags_from_mask(unsigned int mask);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,142 @@
|
|||
##
|
||||
## This file is part of the libsigrok project.
|
||||
##
|
||||
## Copyright (C) 2014 Martin Ling <martin-sigrok@earth.li>
|
||||
##
|
||||
## This program is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
from pygccxml import parser, declarations
|
||||
from collections import OrderedDict
|
||||
import sys, os, re
|
||||
|
||||
# Get directory this script is in.
|
||||
dirname = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# Parse GCCXML output to get declaration tree.
|
||||
decls = parser.parse_xml_file(
|
||||
os.path.join(dirname, "libsigrok.xml"), parser.config_t())
|
||||
|
||||
# Get global namespace from declaration tree.
|
||||
ns = declarations.get_global_namespace(decls)
|
||||
|
||||
mapping = dict([
|
||||
('sr_loglevel', 'LogLevel'),
|
||||
('sr_packettype', 'PacketType'),
|
||||
('sr_mq', 'Quantity'),
|
||||
('sr_unit', 'Unit'),
|
||||
('sr_mqflag', 'QuantityFlag'),
|
||||
('sr_configkey', 'ConfigKey'),
|
||||
('sr_datatype', 'DataType'),
|
||||
('sr_channeltype', 'ChannelType'),
|
||||
('sr_trigger_matches', 'TriggerMatchType')])
|
||||
|
||||
classes = OrderedDict()
|
||||
|
||||
# Build mapping between class names and enumerations.
|
||||
for enum in ns.enumerations():
|
||||
if enum.name in mapping:
|
||||
classname = mapping[enum.name]
|
||||
classes[classname] = enum
|
||||
|
||||
header = open(os.path.join(dirname, 'include/libsigrok/enums.hpp'), 'w')
|
||||
code = open(os.path.join(dirname, 'enums.cpp'), 'w')
|
||||
|
||||
for file in (header, code):
|
||||
print >> file, "/* Generated file - edit enums.py instead! */"
|
||||
|
||||
# Template for beginning of class declaration and public members.
|
||||
header_public_template = """
|
||||
class SR_API {classname} : public EnumValue<enum {enumname}>
|
||||
{{
|
||||
public:
|
||||
static const {classname} *get(int id);
|
||||
"""
|
||||
|
||||
# Template for beginning of private members.
|
||||
header_private_template = """
|
||||
private:
|
||||
static const std::map<enum {enumname}, const {classname} *> values;
|
||||
{classname}(enum {enumname} id, const char name[]);
|
||||
"""
|
||||
|
||||
# Template for class method definitions.
|
||||
code_template = """
|
||||
{classname}::{classname}(enum {enumname} id, const char name[]) :
|
||||
EnumValue<enum {enumname}>(id, name)
|
||||
{{
|
||||
}}
|
||||
|
||||
const {classname} *{classname}::get(int id)
|
||||
{{
|
||||
return {classname}::values.at(static_cast<{enumname}>(id));
|
||||
}}
|
||||
"""
|
||||
|
||||
for classname, enum in classes.items():
|
||||
|
||||
# Begin class and public declarations
|
||||
print >> header, header_public_template.format(
|
||||
classname=classname, enumname=enum.name)
|
||||
|
||||
# Declare public pointers for each enum value
|
||||
for name, value in enum.values:
|
||||
trimmed_name = re.sub("^SR_[A-Z]+_", "", name)
|
||||
print >> header, '\tstatic const %s * const %s;' % (classname, trimmed_name)
|
||||
|
||||
# Declare additional methods if present
|
||||
filename = os.path.join(dirname, "%s_methods.hpp" % classname)
|
||||
if os.path.exists(filename):
|
||||
print >> header, str.join('', open(filename).readlines())
|
||||
|
||||
# Begin private declarations
|
||||
print >> header, header_private_template.format(
|
||||
classname=classname, enumname=enum.name)
|
||||
|
||||
# Declare private constants for each enum value
|
||||
for name, value in enum.values:
|
||||
trimmed_name = re.sub("^SR_[A-Z]+_", "", name)
|
||||
print >> header, '\tstatic const %s _%s;' % (classname, trimmed_name)
|
||||
|
||||
# End class declaration
|
||||
print >> header, '};'
|
||||
|
||||
# Begin class code
|
||||
print >> code, code_template.format(
|
||||
classname=classname, enumname=enum.name)
|
||||
|
||||
# Define private constants for each enum value
|
||||
for name, value in enum.values:
|
||||
trimmed_name = re.sub("^SR_[A-Z]+_", "", name)
|
||||
print >> code, 'const %s %s::_%s = %s(%s, "%s");' % (
|
||||
classname, classname, trimmed_name, classname, name, trimmed_name)
|
||||
|
||||
# Define public pointers for each enum value
|
||||
for name, value in enum.values:
|
||||
trimmed_name = re.sub("^SR_[A-Z]+_", "", name)
|
||||
print >> code, 'const %s * const %s::%s = &%s::_%s;' % (
|
||||
classname, classname, trimmed_name, classname, trimmed_name)
|
||||
|
||||
# Define map of enum values to constants
|
||||
print >> code, 'const std::map<enum %s, const %s *> %s::values = {' % (
|
||||
enum.name, classname, classname)
|
||||
for name, value in enum.values:
|
||||
trimmed_name = re.sub("^SR_[A-Z]+_", "", name)
|
||||
print >> code, '\t{%s, %s::%s},' % (name, classname, trimmed_name)
|
||||
print >> code, '};'
|
||||
|
||||
# Define additional methods if present
|
||||
filename = os.path.join(dirname, "%s_methods.cpp" % classname)
|
||||
if os.path.exists(filename):
|
||||
print >> code, str.join('', open(filename).readlines())
|
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013-2014 Martin Ling <martin-sigrok@earth.li>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBSIGROK_HPP
|
||||
#define LIBSIGROK_HPP
|
||||
|
||||
#include "libsigrok/libsigrok.h"
|
||||
#include <glibmm-2.4/glibmm.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace sigrok
|
||||
{
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* Forward declarations */
|
||||
class SR_API Error;
|
||||
class SR_API Context;
|
||||
class SR_API Driver;
|
||||
class SR_API Device;
|
||||
class SR_API HardwareDevice;
|
||||
class SR_API Channel;
|
||||
class SR_API EventSource;
|
||||
class SR_API Session;
|
||||
class SR_API ConfigKey;
|
||||
class SR_API InputFormat;
|
||||
class SR_API OutputFormat;
|
||||
class SR_API LogLevel;
|
||||
class SR_API ChannelGroup;
|
||||
class SR_API Trigger;
|
||||
class SR_API TriggerStage;
|
||||
class SR_API TriggerMatch;
|
||||
class SR_API TriggerMatchType;
|
||||
class SR_API ChannelType;
|
||||
class SR_API Packet;
|
||||
class SR_API PacketPayload;
|
||||
class SR_API PacketType;
|
||||
class SR_API Quantity;
|
||||
class SR_API Unit;
|
||||
class SR_API QuantityFlag;
|
||||
class SR_API InputFileDevice;
|
||||
class SR_API Output;
|
||||
class SR_API DataType;
|
||||
|
||||
/** Exception thrown when an error code is returned by any libsigrok call. */
|
||||
class SR_API Error: public exception
|
||||
{
|
||||
public:
|
||||
Error(int result);
|
||||
~Error() throw();
|
||||
const int result;
|
||||
const char *what() const throw();
|
||||
};
|
||||
|
||||
/** Base template for most classes which wrap a struct type from libsigrok. */
|
||||
template <class Parent, typename Struct> class SR_API StructureWrapper :
|
||||
public enable_shared_from_this<StructureWrapper<Parent, Struct> >
|
||||
{
|
||||
public:
|
||||
/** Parent object which owns this child object's underlying structure.
|
||||
|
||||
This shared pointer will be null when this child is unused, but
|
||||
will be assigned to point to the parent before any shared pointer
|
||||
to this child is handed out to the user.
|
||||
|
||||
When the reference count of this child falls to zero, this shared
|
||||
pointer to its parent is reset by a custom deleter on the child's
|
||||
shared pointer.
|
||||
|
||||
This strategy ensures that the destructors for both the child and
|
||||
the parent are called at the correct time, i.e. only when all
|
||||
references to both the parent and all its children are gone. */
|
||||
shared_ptr<Parent> parent;
|
||||
protected:
|
||||
Struct *structure;
|
||||
|
||||
StructureWrapper<Parent, Struct>(Struct *structure) :
|
||||
structure(structure)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** Type of log callback */
|
||||
typedef function<void(const LogLevel *, string message)> LogCallbackFunction;
|
||||
|
||||
/** Context */
|
||||
class SR_API Context : public enable_shared_from_this<Context>
|
||||
{
|
||||
public:
|
||||
/** Create new context */
|
||||
static shared_ptr<Context> create();
|
||||
/** libsigrok package version. */
|
||||
string get_package_version();
|
||||
/** libsigrok library version. */
|
||||
string get_lib_version();
|
||||
/** Available hardware drivers, indexed by name. */
|
||||
map<string, shared_ptr<Driver> > get_drivers();
|
||||
/** Available input formats, indexed by name. */
|
||||
map<string, shared_ptr<InputFormat> > get_input_formats();
|
||||
/** Available output formats, indexed by name. */
|
||||
map<string, shared_ptr<OutputFormat> > get_output_formats();
|
||||
/** Current log level. */
|
||||
const LogLevel *get_log_level();
|
||||
/** Set the log level. */
|
||||
void set_log_level(const LogLevel *level);
|
||||
/** Current log domain. */
|
||||
string get_log_domain();
|
||||
/** Set the log domain. */
|
||||
void set_log_domain(string value);
|
||||
/** Set the log callback. */
|
||||
void set_log_callback(LogCallbackFunction callback);
|
||||
/** Set the log callback to the default handler. */
|
||||
void set_log_callback_default();
|
||||
/** Create a new session. */
|
||||
shared_ptr<Session> create_session();
|
||||
/** Load a saved session. */
|
||||
shared_ptr<Session> load_session(string filename);
|
||||
/** Create a new trigger. */
|
||||
shared_ptr<Trigger> create_trigger(string name);
|
||||
protected:
|
||||
struct sr_context *structure;
|
||||
map<string, Driver *> drivers;
|
||||
map<string, InputFormat *> input_formats;
|
||||
map<string, OutputFormat *> output_formats;
|
||||
Session *session;
|
||||
LogCallbackFunction log_callback;
|
||||
Context();
|
||||
~Context();
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(Context *context) { delete context; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class Session;
|
||||
friend class Driver;
|
||||
};
|
||||
|
||||
/** Hardware driver */
|
||||
class SR_API Driver : public StructureWrapper<Context, struct sr_dev_driver>
|
||||
{
|
||||
public:
|
||||
/** Name of this driver. */
|
||||
string get_name();
|
||||
/** Long name for this driver. */
|
||||
string get_long_name();
|
||||
/** Scan for devices and return a list of devices found. */
|
||||
vector<shared_ptr<HardwareDevice> > scan(
|
||||
map<const ConfigKey *, Glib::VariantBase> options = {});
|
||||
protected:
|
||||
bool initialized;
|
||||
vector<HardwareDevice *> devices;
|
||||
Driver(struct sr_dev_driver *structure);
|
||||
~Driver();
|
||||
friend class Context;
|
||||
friend class HardwareDevice;
|
||||
friend class ChannelGroup;
|
||||
};
|
||||
|
||||
/** An object that can be configured. */
|
||||
class SR_API Configurable
|
||||
{
|
||||
public:
|
||||
/** Read configuration for the given key. */
|
||||
Glib::VariantBase config_get(const ConfigKey *key);
|
||||
/** Set configuration for the given key to a specified value. */
|
||||
void config_set(const ConfigKey *key, Glib::VariantBase value);
|
||||
/** Enumerate available values for the given configuration key. */
|
||||
Glib::VariantBase config_list(const ConfigKey *key);
|
||||
protected:
|
||||
Configurable(
|
||||
struct sr_dev_driver *driver,
|
||||
struct sr_dev_inst *sdi,
|
||||
struct sr_channel_group *channel_group);
|
||||
virtual ~Configurable();
|
||||
struct sr_dev_driver *config_driver;
|
||||
struct sr_dev_inst *config_sdi;
|
||||
struct sr_channel_group *config_channel_group;
|
||||
};
|
||||
|
||||
/** Generic device (may be real or from an input file) */
|
||||
class SR_API Device :
|
||||
public Configurable,
|
||||
public StructureWrapper<Context, struct sr_dev_inst>
|
||||
{
|
||||
public:
|
||||
/** Vendor name for this device. */
|
||||
string get_vendor();
|
||||
/** Model name for this device. */
|
||||
string get_model();
|
||||
/** Version string for this device. */
|
||||
string get_version();
|
||||
/** List of the channels available on this device. */
|
||||
vector<shared_ptr<Channel> > get_channels();
|
||||
/** Open device. */
|
||||
void open();
|
||||
/** Close device. */
|
||||
void close();
|
||||
protected:
|
||||
Device(struct sr_dev_inst *structure);
|
||||
~Device();
|
||||
vector<Channel *> channels;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(Device *device) { delete device; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class Session;
|
||||
friend class Channel;
|
||||
friend class ChannelGroup;
|
||||
friend class Output;
|
||||
};
|
||||
|
||||
/** Hardware device (connected via a driver) */
|
||||
class SR_API HardwareDevice : public Device
|
||||
{
|
||||
public:
|
||||
/** Driver providing this device. */
|
||||
shared_ptr<Driver> get_driver();
|
||||
/** Channel groups available on this device, indexed by name. */
|
||||
map<string, shared_ptr<ChannelGroup> > get_channel_groups();
|
||||
protected:
|
||||
HardwareDevice(Driver *driver, struct sr_dev_inst *structure);
|
||||
~HardwareDevice();
|
||||
Driver *driver;
|
||||
map<string, ChannelGroup *> channel_groups;
|
||||
friend class Driver;
|
||||
friend class ChannelGroup;
|
||||
};
|
||||
|
||||
/** Channel */
|
||||
class SR_API Channel : public StructureWrapper<Device, struct sr_channel>
|
||||
{
|
||||
public:
|
||||
/** Current name of this channel. */
|
||||
string get_name();
|
||||
/** Set the name of this channel. */
|
||||
void set_name(string name);
|
||||
/** Type of this channel. */
|
||||
const ChannelType *get_type();
|
||||
/** Enabled status of this channel. */
|
||||
bool get_enabled();
|
||||
/** Set the enabled status of this channel. */
|
||||
void set_enabled(bool value);
|
||||
protected:
|
||||
Channel(struct sr_channel *structure);
|
||||
~Channel();
|
||||
const ChannelType * const type;
|
||||
friend class Device;
|
||||
friend class ChannelGroup;
|
||||
friend class Session;
|
||||
friend class TriggerStage;
|
||||
};
|
||||
|
||||
/** Channel group */
|
||||
class SR_API ChannelGroup :
|
||||
public StructureWrapper<HardwareDevice, struct sr_channel_group>,
|
||||
public Configurable
|
||||
{
|
||||
public:
|
||||
/** Name of this channel group. */
|
||||
string get_name();
|
||||
/** List of the channels in this group. */
|
||||
vector<shared_ptr<Channel> > get_channels();
|
||||
protected:
|
||||
ChannelGroup(HardwareDevice *device, struct sr_channel_group *structure);
|
||||
~ChannelGroup();
|
||||
vector<Channel *> channels;
|
||||
friend class HardwareDevice;
|
||||
};
|
||||
|
||||
/** Trigger */
|
||||
class SR_API Trigger : public enable_shared_from_this<Trigger>
|
||||
{
|
||||
public:
|
||||
string get_name();
|
||||
vector<shared_ptr<TriggerStage> > get_stages();
|
||||
shared_ptr<TriggerStage> add_stage();
|
||||
protected:
|
||||
Trigger(shared_ptr<Context> context, string name);
|
||||
~Trigger();
|
||||
struct sr_trigger *structure;
|
||||
shared_ptr<Context> context;
|
||||
vector<TriggerStage *> stages;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(Trigger *trigger) { delete trigger; }
|
||||
};
|
||||
friend class Context;
|
||||
};
|
||||
|
||||
/** Trigger stage */
|
||||
class SR_API TriggerStage : public StructureWrapper<Trigger, struct sr_trigger_stage>
|
||||
{
|
||||
public:
|
||||
int get_number();
|
||||
vector<shared_ptr<TriggerMatch> > get_matches();
|
||||
void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type);
|
||||
void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type, float value);
|
||||
protected:
|
||||
vector<TriggerMatch *> matches;
|
||||
TriggerStage(struct sr_trigger_stage *structure);
|
||||
~TriggerStage();
|
||||
friend class Trigger;
|
||||
};
|
||||
|
||||
/** Trigger match */
|
||||
class SR_API TriggerMatch : public StructureWrapper<TriggerStage, struct sr_trigger_match>
|
||||
{
|
||||
public:
|
||||
shared_ptr<Channel> get_channel();
|
||||
const TriggerMatchType *get_type();
|
||||
float get_value();
|
||||
protected:
|
||||
TriggerMatch(struct sr_trigger_match *structure, shared_ptr<Channel> channel);
|
||||
~TriggerMatch();
|
||||
shared_ptr<Channel> channel;
|
||||
friend class TriggerStage;
|
||||
};
|
||||
|
||||
/** Type of datafeed callback */
|
||||
typedef function<void(shared_ptr<Device>, shared_ptr<Packet>)>
|
||||
DatafeedCallbackFunction;
|
||||
|
||||
/** Data required for C callback function to call a C++ datafeed callback */
|
||||
class SR_PRIV DatafeedCallbackData
|
||||
{
|
||||
public:
|
||||
void run(const struct sr_dev_inst *sdi,
|
||||
const struct sr_datafeed_packet *pkt);
|
||||
protected:
|
||||
DatafeedCallbackFunction callback;
|
||||
DatafeedCallbackData(Session *session,
|
||||
DatafeedCallbackFunction callback);
|
||||
Session *session;
|
||||
friend class Session;
|
||||
};
|
||||
|
||||
/** Type of source callback */
|
||||
typedef function<bool(Glib::IOCondition)>
|
||||
SourceCallbackFunction;
|
||||
|
||||
/** Data required for C callback function to call a C++ source callback */
|
||||
class SR_PRIV SourceCallbackData
|
||||
{
|
||||
public:
|
||||
bool run(int revents);
|
||||
protected:
|
||||
SourceCallbackData(shared_ptr<EventSource> source);
|
||||
shared_ptr<EventSource> source;
|
||||
friend class Session;
|
||||
};
|
||||
|
||||
/** Event source. */
|
||||
class SR_API EventSource
|
||||
{
|
||||
public:
|
||||
/** Create an event source from a file descriptor. */
|
||||
static shared_ptr<EventSource> create(int fd, Glib::IOCondition events,
|
||||
int timeout, SourceCallbackFunction callback);
|
||||
/** Create an event source from a Glib::PollFD */
|
||||
static shared_ptr<EventSource> create(Glib::PollFD pollfd, int timeout,
|
||||
SourceCallbackFunction callback);
|
||||
/** Create an event source from a Glib::IOChannel */
|
||||
static shared_ptr<EventSource> create(
|
||||
Glib::RefPtr<Glib::IOChannel> channel, Glib::IOCondition events,
|
||||
int timeout, SourceCallbackFunction callback);
|
||||
protected:
|
||||
EventSource(int timeout, SourceCallbackFunction callback);
|
||||
~EventSource();
|
||||
enum source_type {
|
||||
SOURCE_FD,
|
||||
SOURCE_POLLFD,
|
||||
SOURCE_IOCHANNEL
|
||||
} type;
|
||||
int fd;
|
||||
Glib::PollFD pollfd;
|
||||
Glib::RefPtr<Glib::IOChannel> channel;
|
||||
Glib::IOCondition events;
|
||||
int timeout;
|
||||
SourceCallbackFunction callback;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(EventSource *source) { delete source; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class Session;
|
||||
friend class SourceCallbackData;
|
||||
};
|
||||
|
||||
/** Session */
|
||||
class SR_API Session
|
||||
{
|
||||
public:
|
||||
/** Add a device to this session. */
|
||||
void add_device(shared_ptr<Device> device);
|
||||
/** List devices attached to this session. */
|
||||
vector<shared_ptr<Device> > get_devices();
|
||||
/** Remove all devices from this session. */
|
||||
void remove_devices();
|
||||
/** Add a datafeed callback to this session. */
|
||||
void add_datafeed_callback(DatafeedCallbackFunction callback);
|
||||
/** Remove all datafeed callbacks from this session. */
|
||||
void remove_datafeed_callbacks();
|
||||
/** Add an event source. */
|
||||
void add_source(shared_ptr<EventSource> source);
|
||||
/** Remove an event source. */
|
||||
void remove_source(shared_ptr<EventSource> source);
|
||||
/** Start the session. */
|
||||
void start();
|
||||
/** Run the session event loop. */
|
||||
void run();
|
||||
/** Stop the session. */
|
||||
void stop();
|
||||
/** Begin saving session to a file. */
|
||||
void begin_save(string filename);
|
||||
/** Append a packet to the session file being saved. */
|
||||
void append(shared_ptr<Device> device, shared_ptr<Packet> packet);
|
||||
protected:
|
||||
Session(shared_ptr<Context> context);
|
||||
Session(shared_ptr<Context> context, string filename);
|
||||
~Session();
|
||||
struct sr_session *structure;
|
||||
const shared_ptr<Context> context;
|
||||
map<const struct sr_dev_inst *, shared_ptr<Device> > devices;
|
||||
vector<DatafeedCallbackData *> datafeed_callbacks;
|
||||
map<shared_ptr<EventSource>, SourceCallbackData *> source_callbacks;
|
||||
bool saving;
|
||||
bool save_initialized;
|
||||
string save_filename;
|
||||
uint64_t save_samplerate;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(Session *session) { delete session; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class Context;
|
||||
friend class DatafeedCallbackData;
|
||||
};
|
||||
|
||||
/** Datafeed packet */
|
||||
class SR_API Packet
|
||||
{
|
||||
public:
|
||||
/** Payload of this packet. */
|
||||
PacketPayload *get_payload();
|
||||
protected:
|
||||
Packet(const struct sr_datafeed_packet *structure);
|
||||
~Packet();
|
||||
const struct sr_datafeed_packet *structure;
|
||||
PacketPayload *payload;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(Packet *packet) { delete packet; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class Session;
|
||||
friend class Output;
|
||||
friend class DatafeedCallbackData;
|
||||
};
|
||||
|
||||
/** Abstract base class for datafeed packet payloads. */
|
||||
class SR_API PacketPayload
|
||||
{
|
||||
protected:
|
||||
PacketPayload();
|
||||
virtual ~PacketPayload() = 0;
|
||||
virtual void *get_data() = 0;
|
||||
virtual size_t get_data_size() = 0;
|
||||
friend class Packet;
|
||||
friend class Output;
|
||||
};
|
||||
|
||||
/** Logic data payload */
|
||||
class SR_API Logic : public PacketPayload
|
||||
{
|
||||
protected:
|
||||
Logic(const struct sr_datafeed_logic *structure);
|
||||
~Logic();
|
||||
const struct sr_datafeed_logic *structure;
|
||||
vector<uint8_t> data;
|
||||
void *get_data();
|
||||
size_t get_data_size();
|
||||
friend class Packet;
|
||||
};
|
||||
|
||||
/** Analog data payload */
|
||||
class SR_API Analog : public PacketPayload
|
||||
{
|
||||
public:
|
||||
/** Number of samples in this packet. */
|
||||
unsigned int get_num_samples();
|
||||
/** Measured quantity of the samples in this packet. */
|
||||
const Quantity *get_mq();
|
||||
/** Unit of the samples in this packet. */
|
||||
const Unit *get_unit();
|
||||
/** Measurement flags associated with the samples in this packet. */
|
||||
vector<const QuantityFlag *> get_mq_flags();
|
||||
protected:
|
||||
Analog(const struct sr_datafeed_analog *structure);
|
||||
~Analog();
|
||||
const struct sr_datafeed_analog *structure;
|
||||
void *get_data();
|
||||
size_t get_data_size();
|
||||
friend class Packet;
|
||||
};
|
||||
|
||||
/** Input format */
|
||||
class SR_API InputFormat :
|
||||
public StructureWrapper<Context, struct sr_input_format>
|
||||
{
|
||||
public:
|
||||
/** Name of this input format. */
|
||||
string get_name();
|
||||
/** Description of this input format. */
|
||||
string get_description();
|
||||
/** Check whether a given file matches this input format. */
|
||||
bool format_match(string filename);
|
||||
/** Open a file using this input format. */
|
||||
shared_ptr<InputFileDevice> open_file(string filename,
|
||||
map<string, string> options = {});
|
||||
protected:
|
||||
InputFormat(struct sr_input_format *structure);
|
||||
~InputFormat();
|
||||
friend class Context;
|
||||
friend class InputFileDevice;
|
||||
};
|
||||
|
||||
/** Virtual device associated with an input file */
|
||||
class SR_API InputFileDevice : public Device
|
||||
{
|
||||
public:
|
||||
/** Load data from file. */
|
||||
void load();
|
||||
protected:
|
||||
InputFileDevice(shared_ptr<InputFormat> format,
|
||||
struct sr_input *input, string filename);
|
||||
~InputFileDevice();
|
||||
struct sr_input *input;
|
||||
shared_ptr<InputFormat> format;
|
||||
string filename;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(InputFileDevice *device) { delete device; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class InputFormat;
|
||||
};
|
||||
|
||||
/** Output format */
|
||||
class SR_API OutputFormat :
|
||||
public StructureWrapper<Context, struct sr_output_format>
|
||||
{
|
||||
public:
|
||||
/** Name of this output format. */
|
||||
string get_name();
|
||||
/** Description of this output format. */
|
||||
string get_description();
|
||||
/** Create an output using this format. */
|
||||
shared_ptr<Output> create_output(shared_ptr<Device> device, map<string, string> options = {});
|
||||
protected:
|
||||
OutputFormat(struct sr_output_format *structure);
|
||||
~OutputFormat();
|
||||
friend class Context;
|
||||
friend class Output;
|
||||
};
|
||||
|
||||
/** Output instance (an output format applied to a device) */
|
||||
class SR_API Output
|
||||
{
|
||||
public:
|
||||
/** Update output with data from the given packet. */
|
||||
string receive(shared_ptr<Packet> packet);
|
||||
protected:
|
||||
Output(shared_ptr<OutputFormat> format, shared_ptr<Device> device);
|
||||
Output(shared_ptr<OutputFormat> format,
|
||||
shared_ptr<Device> device, map<string, string> options);
|
||||
~Output();
|
||||
struct sr_output *structure;
|
||||
const shared_ptr<OutputFormat> format;
|
||||
const shared_ptr<Device> device;
|
||||
const map<string, string> options;
|
||||
/** Deleter needed to allow shared_ptr use with protected destructor. */
|
||||
class Deleter
|
||||
{
|
||||
public:
|
||||
void operator()(Output *output) { delete output; }
|
||||
};
|
||||
friend class Deleter;
|
||||
friend class OutputFormat;
|
||||
};
|
||||
|
||||
/** Base class for objects which wrap an enumeration value from libsigrok */
|
||||
template <typename T> class SR_API EnumValue
|
||||
{
|
||||
public:
|
||||
/** The enum constant associated with this value. */
|
||||
T get_id() const { return id; }
|
||||
/** The name associated with this value. */
|
||||
string get_name() const { return name; }
|
||||
protected:
|
||||
EnumValue(T id, const char name[]) : id(id), name(name) {}
|
||||
~EnumValue() {}
|
||||
const T id;
|
||||
const string name;
|
||||
};
|
||||
|
||||
#include "enums.hpp"
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBSIGROK_HPP
|
|
@ -0,0 +1,15 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libsigrokxx
|
||||
Description: C++ bindings for libsigrok
|
||||
URL: http://www.sigrok.org
|
||||
Requires: libsigrok glibmm-2.4
|
||||
Requires.private: @SR_PKGLIBS@
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lsigrokxx
|
||||
Libs.private: -lm
|
||||
Cflags: -I${includedir}
|
||||
|
31
configure.ac
31
configure.ac
|
@ -46,10 +46,12 @@ AH_BOTTOM([#endif /* SR_CONFIG_H */])
|
|||
# and enforce use of SR_API to explicitly mark all public API functions.
|
||||
COMMON_FLAGS="$CFLAGS -Wall -Wextra -fvisibility=hidden"
|
||||
CFLAGS="$COMMON_FLAGS -Wmissing-prototypes"
|
||||
CXXFLAGS="-std=c++11 $COMMON_FLAGS"
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
|
||||
|
@ -152,6 +154,21 @@ AC_ARG_ENABLE(libusb,
|
|||
AC_HELP_STRING([--disable-libusb],
|
||||
[disable libusb support [default=detect]]))
|
||||
|
||||
# Language binding '--enable' options
|
||||
|
||||
AC_ARG_ENABLE(c++,
|
||||
AC_HELP_STRING([--enable-cxx],
|
||||
[build C++ bindings [default=yes]]),
|
||||
[BINDINGS_CXX="$enableval"], [BINDINGS_CXX="yes"])
|
||||
|
||||
# Check if the C++ compiler supports the C++11 standard.
|
||||
|
||||
AX_CXX_COMPILE_STDCXX_11(,[optional])
|
||||
|
||||
if test "x$HAVE_CXX11" != "x1"; then
|
||||
BINDINGS_CXX="no"
|
||||
fi
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
case "$host" in
|
||||
|
@ -301,6 +318,11 @@ if test "x$have_libftdi" = "xno"; then
|
|||
HW_ASIX_SIGMA="no"; HW_CHRONOVU_LA="no"; HW_IKALOGIC_SCANAPLUS="no";
|
||||
fi
|
||||
|
||||
# glibmm-2.4 is needed for the C++ bindings.
|
||||
PKG_CHECK_MODULES([glibmm], [glibmm-2.4 >= 2.32.0],
|
||||
[CXXFLAGS="$CXXFLAGS $glibmm_CFLAGS";
|
||||
CXXLIBS="$CXXLIBS $glibmm_LIBS"], [BINDINGS_CXX="no"])
|
||||
|
||||
# The Check unit testing framework is optional. Disable if not found.
|
||||
PKG_CHECK_MODULES([check], [check >= 0.9.4],
|
||||
[have_check="yes"], [have_check="no"])
|
||||
|
@ -317,6 +339,7 @@ esac
|
|||
AC_SUBST(SR_PKGLIBS)
|
||||
|
||||
CFLAGS="$CFLAGS -I./include/libsigrok $LIB_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS -I./include -I./bindings/cxx/include $LIB_CFLAGS"
|
||||
|
||||
# Now set AM_CONDITIONALs and AC_DEFINEs for the enabled/disabled drivers.
|
||||
|
||||
|
@ -505,6 +528,8 @@ if test "x$HW_ZEROPLUS_LOGIC_CUBE" = "xyes"; then
|
|||
AC_DEFINE(HAVE_HW_ZEROPLUS_LOGIC_CUBE, 1, [ZEROPLUS Logic Cube support])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(BINDINGS_CXX, test x$BINDINGS_CXX = xyes)
|
||||
|
||||
# Checks for header files.
|
||||
# These are already checked: inttypes.h stdint.h stdlib.h string.h unistd.h.
|
||||
|
||||
|
@ -525,7 +550,8 @@ AC_SUBST(SR_PACKAGE_VERSION_MINOR)
|
|||
AC_SUBST(SR_PACKAGE_VERSION_MICRO)
|
||||
AC_SUBST(SR_PACKAGE_VERSION)
|
||||
|
||||
AC_CONFIG_FILES([Makefile include/libsigrok/version.h libsigrok.pc])
|
||||
AC_CONFIG_FILES([Makefile include/libsigrok/version.h libsigrok.pc
|
||||
bindings/cxx/libsigrokxx.pc])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
|
@ -557,3 +583,6 @@ done
|
|||
|
||||
echo -e "\nEnabled hardware drivers:\n${driver_summary}"
|
||||
|
||||
echo -e "\nEnabled language bindings:\n"
|
||||
echo " - C++............................. $BINDINGS_CXX"
|
||||
echo
|
||||
|
|
Loading…
Reference in New Issue