As the 2 classes/objects are inter-dependent, I think it's better to include
both into the same .oct file. What's happening is that channel.oct is not
loaded into memory when octave loads analoginput.oct, leading to unresolved
references. This does not happen when channel.oct is loaded explicitely
first.

This is only possible, because Linux (and the like) allows to have
unresolved references at link time. This wouldn't work under Windows
for instance (or you would have to link one oct file against the other one).

Michael.


2010/6/16 Pablo Daniel Pareja Obregón <parejaobre...@gmail.com>:
> Hi,
>
> I want to implement a "data acquisition package" equivalent to the one
> present in Matlab. The main purpose is to access hardware with
> measurement purposes (from Measurement Computing and Texas Instruments
> for example). The idea is to release it as gpl and when finished
> include it as an octave package. The needed drivers for measurement
> computing devices (the ones I intend to implement first, as I have one
> to make tests) are gpl and can be found in [1].
>
> In order to do so, I must implement my own user defined types, as I
> read in [2]. However, after googling a while, I haven't found much
> documentation and examples on how programming my own types (besides
> [2]). I'm not an expert programmer, and I don't know if I'm taking the
> right approach.
>
> The problem I have is that I want to create two classes, the first one
> implements the instruments themselves (called analoginput in Matlab)
> and the second one implements the channels with their corresponding
> data. The first class must have a list of channels that can be added
> through an "addchannel" call. Through a "trigger" call, the first
> class, must also init the data adquisition and pass the data measured
> to the channels.
>
> My first draft looks like:
>
> **********************************************************
> ***************** analoginput.h ************************
> **********************************************************
>
> #ifndef ANALOGINPUT_H
> #define ANALOGINPUT_H
>
> #include <iostream>
> #include <octave/oct.h>
> #include <octave/parse.h>
> #include <octave/dynamic-ld.h>
> #include <octave/oct-map.h>
> #include <octave/oct-stream.h>
> #include <octave/ov-base-scalar.h>
> #include <string>
>
> #include "channel.h"
>
> using namespace std;
>
> class AnalogInput : public octave_base_value
> {
> public:
>    AnalogInput(void);
>    AnalogInput(octave_value instr_val);
>    AnalogInput(string type);
>
>    ~AnalogInput(void);
>
>    string*  get_str(void) const;
>
>    void print(std::ostream& os, bool pr_as_read_syntax = false) const;
>    Channel* addchannel() const;
>
>    bool is_constant(void) const { return true; }
>    bool is_defined(void) const { return true; }
>
> private:
>    string *objtype;
>
>    // I will implement a list of channels here
>
>    DECLARE_OCTAVE_ALLOCATOR
>    DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
> };
>
> DEFINE_OCTAVE_ALLOCATOR(AnalogInput);
> DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(AnalogInput, "AnalogInput",
> "AnalogInput");
>
> #endif // ANALOGINPUT_H
>
>
> **********************************************************
> **************** analoginput.cpp **********************
> **********************************************************
>
> #include "analoginput.h"
>
>
> AnalogInput::AnalogInput(void) : octave_base_value()
> {
>    objtype = new string("None");
> }
>
> AnalogInput::AnalogInput(octave_value instr_val) : octave_base_value()
> {
>    const octave_base_value& rep = instr_val.get_rep();
>    objtype = ((const AnalogInput&) rep).get_str();
> }
>
> AnalogInput::AnalogInput(string type) : octave_base_value()
> {
>    objtype = new string(type);
> }
>
> AnalogInput::~AnalogInput(void)
> {
> }
>
> string* AnalogInput::get_str(void) const
> {
>    return this->objtype;
> }
>
> void AnalogInput::print(std::ostream& os, bool pr_as_read_syntax) const
> {
>    os << "Instrument = " << *get_str() << endl;
> }
>
> Channel* AnalogInput::addchannel() const
> {
>    Channel* newChannel = new Channel();
>
>    // Add the channel to the list here
>
>    return newChannel;
> }
>
>
> DEFUN_DLD(analoginput, args, , "analoginput('adaptor')\n\
>          Makes new instances of instrument objects")
> {
>    if(args.length() < 1){
>        cout << "usage: analoginput('adaptor')\n";
>        return octave_value();
>    }
>
>    AnalogInput *b = new AnalogInput(args(0).string_value());
>    return octave_value(b);
> }
>
> DEFUN_DLD(addchannel, args, , "addchannel(AnalogInputObject, ID)\n\
>          Adds a new analog channel to the adaptor")
> {
>    // This is yet to be implemented. Here I call the addchannel procedure,
>    // and return the generated channel as a result.
>    return octave_value(-1);
> }
>
>
> **********************************************************
> ******************** channel.h *************************
> **********************************************************
> #ifndef CHANNEL_H
> #define CHANNEL_H
>
> #include <iostream>
> #include <octave/oct.h>
> #include <octave/parse.h>
> #include <octave/dynamic-ld.h>
> #include <octave/oct-map.h>
> #include <octave/oct-stream.h>
> #include <octave/ov-base-scalar.h>
> #include <string>
>
> using namespace std;
>
> class Channel : public octave_base_value
> {
> public:
>    Channel(void);
>    Channel(octave_value instr_val);
>    Channel(string type);
>
>    ~Channel(void);
>
>    string*  get_str(void) const;
>
>    void print(std::ostream& os, bool pr_as_read_syntax = false) const;
>
>    bool is_constant(void) const { return true; }
>    bool is_defined(void) const { return true; }
>
> private:
>    string *objtype;
>
>    DECLARE_OCTAVE_ALLOCATOR
>    DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
> };
>
> DEFINE_OCTAVE_ALLOCATOR(Channel);
> DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(Channel, "Channel", "Channel");
>
> #endif // CHANNEL_H
>
> **********************************************************
> ******************* channel.cpp ***********************
> **********************************************************
>
> #include "channel.h"
>
> Channel::Channel(void) : octave_base_value()
> {
>    objtype = new string("None");
> }
>
> Channel::Channel(octave_value instr_val) : octave_base_value()
> {
>    const octave_base_value& rep = instr_val.get_rep();
>    objtype = ((const Channel&) rep).get_str();
> }
>
> Channel::Channel(string type) : octave_base_value()
> {
>    objtype = new string(type);
> }
>
> Channel::~Channel(void)
> {
> }
>
> string* Channel::get_str(void) const
> {
>    return this->objtype;
> }
>
> void Channel::print(std::ostream& os, bool pr_as_read_syntax) const
> {
>    os << "Instrument = " << *get_str() << endl;
> }
>
>
> DEFUN_DLD(channel, args, , "channel('adaptor')\n\
>          Makes new instances of instrument objects")
> {
>    if(args.length() < 1){
>        cout << "usage: channel('adaptor')\n";
>        return octave_value();
>    }
>
>    Channel *b = new Channel(args(0).string_value());
>    return octave_value(b);
> }
>
> **********************************************************
>
> I compile the sources with the following commands:
>
> mkoctfile channel.cpp
> mkoctfile analoginput.cpp -o analoginput.oct
> ln -s analoginput.oct addchannel.oct
>
>
> The compilation has no errors. However, when I try to use the newly
> defined objects in octave, if I try to create the analoginput I get
> the following error:
>
> error: /......./analoginput.oct: undefined symbol: _ZN7ChannelC1Ev
>
> On the other hand, if I create any channel fist, and after that I
> create an analoginput (with no relation with the channel created
> before), I get no errors for the rest of the octave session.
>
> Any ideas how should I fix this? Any suggestion on a better way to
> implement the functions of this package, or anyone wanting to
> contribute is welcome.
>
> Thanks you for your help.
>
> Regards,
> Pablo
>
> --
>
> [1] ftp://lx10.tx.ncsu.edu/pub/Linux/drivers/
> [2] http://wiki.octave.org/wiki.pl?CodaTypes
>
> ------------------------------------------------------------------------------
> ThinkGeek and WIRED's GeekDad team up for the Ultimate
> GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the
> lucky parental unit.  See the prize list and enter to win:
> http://p.sf.net/sfu/thinkgeek-promo
> _______________________________________________
> Octave-dev mailing list
> Octave-dev@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/octave-dev
>

------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate 
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the 
lucky parental unit.  See the prize list and enter to win: 
http://p.sf.net/sfu/thinkgeek-promo
_______________________________________________
Octave-dev mailing list
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to