Skip to content

Instantly share code, notes, and snippets.

@ryandoyle
Last active December 20, 2015 02:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryandoyle/21ce3cc661a36f22f10f to your computer and use it in GitHub Desktop.
Save ryandoyle/21ce3cc661a36f22f10f to your computer and use it in GitHub Desktop.
Nested Data_Wrap_Struct
static VALUE rb_pmLookupDesc(VALUE self, VALUE pmid) {
pmDesc *pm_desc;
pm_desc = ALLOC(pmDesc);
pmLookupDesc(NUM2UINT(pmid), pm_desc))
return rb_pmapi_pmdesc_new(pm_desc);
}
typedef struct pmUnits {
unsigned int pad : 8;
signed int scaleCount : 4; /* one of PM_COUNT_* below */
unsigned int scaleTime : 4; /* one of PM_TIME_* below */
unsigned int scaleSpace : 4; /* one of PM_SPACE_* below */
signed int dimCount : 4; /* event dimension */
signed int dimTime : 4; /* time dimension */
signed int dimSpace : 4; /* space dimension */
} pmUnits;
typedef struct pmDesc {
pmID pmid; /* unique identifier */
int type; /* base data type (see below) */
pmInDom indom; /* instance domain */
int sem; /* semantics of value (see below) */
pmUnits units; /* dimension and units */
} pmDesc;
static VALUE rb_pmapi_pmdesc_pmunits(VALUE self) {
pmUnits *pm_units = &rb_pmapi_pmdesc_ptr(self)->units;
return rb_pmapi_pmunits_new(pm_units);
}
/* This is only ever called when pmDesc is created via native Ruby.
Because we are only memcpy()ing the data, back, it is possible for the
pmUnits class to get out of sync with the underlying pmDesc struct */
static VALUE rb_pmapi_pmdesc_pmunits_set(VALUE self, VALUE pm_units) {
pmUnits *pm_units_from_pmUnits_class = rb_pmapi_pmunits_get(pm_units);
memcpy(&rb_pmapi_pmdesc_ptr(self)->units, pm_units_from_pmUnits_class, sizeof(pmUnits));
return Qnil;
}
VALUE rb_pmapi_pmdesc_new(pmDesc *pm_desc) {
return Data_Wrap_Struct(pcp_pmapi_pmdesc_class, 0, rb_pmapi_pmdesc_free, pm_desc);
}
void init_rb_pmapi_pmdesc(VALUE pmapi_class) {
...
rb_define_method(pcp_pmapi_pmdesc_class, "units", rb_pmapi_pmdesc_pmunits, 0);
rb_define_private_method(pcp_pmapi_pmdesc_class, "units=", rb_pmapi_pmdesc_pmunits_set, 1);
...
}
/* Allocation via this function requires that the callee is the one that frees pmUnits.
* When this object is created in Ruby code, it allocates and cleans up appropriately.
* When constructed here, its done so by the pmDesc class and its manages the freeing */
VALUE rb_pmapi_pmunits_new(pmUnits *pm_units) {
return Data_Wrap_Struct(pcp_pmapi_pmunits_class, 0, 0, pm_units);
}
static pmUnits* rb_pmapi_pmunits_ptr(VALUE self) {
pmUnits *pm_units;
Data_Get_Struct(self, pmUnits, pm_units);
return pm_units;
}
pmUnits *rb_pmapi_pmunits_get(VALUE self) {
return rb_pmapi_pmunits_ptr(self);
}
require 'pcp/pmapi'
module PCP
class PMAPI
class PmDesc
def initialize(pmid, type, indom, sem, units)
self.pmid = pmid
self.type = type
self.indom = indom
self.sem = sem
raise ::TypeError, "#{units.class} are invalid units. Must be of type PCP::PMAPI::PmUnits" unless units.is_a?(PCP::PMAPI::PmUnits)
self.units = units
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment