// constructor - init all HAL pins, params, funct etc here static int instantiate(const char *name, const int argc, const char**argv) { struct inst_data *ip; // allocate a named instance, and some HAL memory for the instance data int inst_id = hal_inst_create(name, comp_id, sizeof(struct inst_data), (void **)&ip); if (inst_id < 0) return -1; // here ip is guaranteed to point to a blob of HAL memory of size sizeof(struct inst_data). HALERR("inst=%s argc=%d\n", name, argc); HALERR("instance parms: repeat=%d prefix='%s'", repeat, prefix); HALERR("module parms: answer=%d text='%s'", answer, text); // these pins/params/functs will be owned by the instance, and can be separately exited int retval = export_halobjs(ip, inst_id, name); // unittest: echo instance parameters into observer pins if (!retval) { *(ip->repeat_value) = repeat; *(ip->prefix_len) = strlen(prefix); } return retval; }
// init HAL objects static int export_halobjs(struct inst_data *ip, int owner_id, const char *name) { if (rring) { // if given, the ring MUST be a stream type plug_args_t rargs = { .type = PLUG_READER, .flags = RINGTYPE_STREAM, .ring_name = rring, .owner_name = name }; ip->rplug = halg_plug_new(1, &rargs); if (ip->rplug == NULL) return _halerrno; } if (wring) { // this plug accepts any ring type plug_args_t wargs = { .type = PLUG_WRITER, .flags = RINGTYPE_ANY, .ring_name = wring, .owner_name = name }; ip->wplug = halg_plug_new(1, &wargs); if (ip->wplug == NULL) return _halerrno; } // exporting '<instname>.funct' as an extended thread function // see lutn.c for a discussion of advantages hal_export_xfunct_args_t xfunct_args = { .type = FS_XTHREADFUNC, .funct.x = funct, .arg = ip, // the instance's HAL memory blob .uses_fp = 1, .reentrant = 0, .owner_id = owner_id }; return hal_export_xfunctf(&xfunct_args, "%s.funct", name); } // constructor - init all HAL pins, params, funct etc here static int instantiate(const int argc, const char**argv) { // argv[0]: component name const char *name = argv[1]; // instance name struct inst_data *ip; // allocate a named instance, and some HAL memory for the instance data int inst_id = hal_inst_create(name, comp_id, sizeof(struct inst_data), (void **)&ip); if (inst_id < 0) return -1; // here ip is guaranteed to point to a blob of HAL memory // of size sizeof(struct inst_data). HALDBG("inst=%s argc=%d\n", name, argc); HALDBG("instance parms: rring=%s wring=%s", rring, wring); // these pins/params/functs will be owned by the instance, // and can be separately exited 'halcmd delinst <instancename>' int retval = export_halobjs(ip, inst_id, name); return retval; } // custom destructor // pins, params, and functs are automatically deallocated by hal_exit(comp_id) // regardless if a destructor is used or not (see below), so usually it is not // needed // // however, some objects like vtables, rings, threads, signals are not owned by // a component, hence cannot be automatically exited by hal_exit() even if desired // // interaction with such objects may require a custom destructor like below for // cleanup actions // NB: if a customer destructor is used, it is called // - after the instance's functs have been removed from their respective threads // (so a thread funct call cannot interact with the destructor any more) // - any pins, params and plugs of this instance are still intact when the destructor is // called, and they are automatically destroyed by the HAL library once the // destructor returns static int delete(const char *name, void *inst, const int inst_size) { HALDBG("inst=%s size=%d %p\n", name, inst_size, inst); return 0; } int rtapi_app_main(void) { comp_id = hal_xinit(TYPE_RT, 0, 0, instantiate, delete, compname); if (comp_id < 0) return comp_id; hal_ready(comp_id); return 0; }
// init HAL objects static int export_halobjs(struct inst_data *ip, int owner_id, const char *name) { if (hal_pin_float_newf(HAL_OUT, &ip->out, owner_id, "%s.out", name)) return -1; if (hal_pin_float_newf(HAL_IN, &ip->in, owner_id, "%s.in", name)) return -1; if (hal_param_s32_newf(HAL_RO, &ip->iter,owner_id, "%s.iter", name)) return -1; // unittest observer pins, per instance if (hal_pin_s32_newf(HAL_OUT, &ip->repeat_value, owner_id, "%s.repeat_value", name)) return -1; if (hal_pin_s32_newf(HAL_OUT, &ip->prefix_len, owner_id, "%s.prefix_len", name)) return -1; // exporting '<instname>.funct' as an extended thread function // see lutn.c for a discussion of advantages hal_export_xfunct_args_t xfunct_args = { .type = FS_XTHREADFUNC, .funct.x = funct, .arg = ip, // the instance's HAL memory blob .uses_fp = 1, .reentrant = 0, .owner_id = owner_id }; return hal_export_xfunctf(&xfunct_args, "%s.funct", name); } // constructor - init all HAL pins, params, funct etc here static int instantiate(const int argc, const char**argv) { // argv[0]: component name const char *name = argv[1]; // instance name struct inst_data *ip; // allocate a named instance, and some HAL memory for the instance data int inst_id = hal_inst_create(name, comp_id, sizeof(struct inst_data), (void **)&ip); if (inst_id < 0) return -1; // here ip is guaranteed to point to a blob of HAL memory // of size sizeof(struct inst_data). HALINFO("inst=%s argc=%d\n", name, argc); HALINFO("instance parms: repeat=%d prefix='%s'", repeat, prefix); HALINFO("module parms: answer=%d text='%s'", answer, text); // example - parse newinst arguments getopt-style: // straight from: http://www.informit.com/articles/article.aspx?p=175771&seqNum=3 int do_all, do_help, do_verbose; /* flag variables */ char *myfile; struct option longopts[] = { { "all", no_argument, & do_all, 1 }, { "file", required_argument, NULL, 'f' }, { "help", no_argument, & do_help, 1 }, { "verbose", no_argument, & do_verbose, 1 }, { 0, 0, 0, 0 } }; int c; while ((c = getopt_long(argc, argv, ":f:", longopts, NULL)) != -1) { switch (c) { case 'f': myfile = optarg; break; case 0: // getopt_long() set a variable, just keep going break; case ':': // missing option argument HALERR("%s: option `-%c' requires an argument\n", argv[1], optopt); break; case '?': default: // invalid option HALERR("%s: option `-%c' is invalid, ignored", argv[1], optopt); break; } } HALINFO("do_all=%d do_help=%d do_verbose=%d myfile=%s", do_all, do_help, do_verbose, myfile); // these pins/params/functs will be owned by the instance, // and can be separately exited via 'halcmd delinst <instancename>' int retval = export_halobjs(ip, inst_id, name); // unittest: echo instance parameters into observer pins if (!retval) { *(ip->repeat_value) = repeat; *(ip->prefix_len) = strlen(prefix); } return retval; } // custom destructor // pins, params, and functs are automatically deallocated by hal_exit(comp_id) // regardless if a destructor is used or not (see below), so usually it is not // needed // // however, some objects like vtables, rings, threads, signals are not owned by // a component, hence cannot be automatically exited by hal_exit() even if desired // // interaction with such objects may require a custom destructor like below for // cleanup actions // NB: if a customer destructor is used, it is called // - after the instance's functs have been removed from their respective threads // (so a thread funct call cannot interact with the destructor any more) // - any pins and params of this instance are still intact when the destructor is // called, and they are automatically destroyed by the HAL library once the // destructor returns static int delete(const char *name, void *inst, const int inst_size) { HALERR("inst=%s size=%d %p\n", name, inst_size, inst); HALERR("instance parms: repeat=%d prefix='%s'", repeat, prefix); HALERR("module parms: answer=%d text='%s'", answer, text); return 0; } int rtapi_app_main(void) { HALERR("instance parms: repeat=%d prefix='%s'", repeat, prefix); HALERR("module parms: answer=%d text='%s'", answer, text); // to use default destructor, use NULL instead of delete comp_id = hal_xinit(TYPE_RT, 0, 0, instantiate, delete, compname); if (comp_id < 0) return comp_id; #if 0 // this is how an 'instance' would have been done in the legacy way struct inst_data *ip = hal_malloc(sizeof(struct inst_data)); // these pins/params/functs will be owned by the component // NB: this 'instance' cannot be exited, and no new one created on the fly if (export_halobjs(ip, comp_id, "foo")) return -1; #endif // unittest only, see nosetests/unittest_instbindings.py and // nosetests/unittest_icomp.py // purpose: echo module params into observer pins // (cant set pins to strings, so just echo the string length) if ((cd = export_observer_pins(comp_id, compname)) == NULL) return -1; *(cd->answer_value) = answer; *(cd->text_len) = strlen(text); hal_ready(comp_id); return 0; }