EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: octave interface
From: "D. Peter Siddons" <[email protected]>
To: [email protected]
Date: Tue, 17 Jan 2006 17:52:50 -0500
Some time ago I posted a simple interface to CA from the Octave language. I just discovered a stupid typo which caused segfaults for some array puts. Attached is a revised version of the c++ file. The rest is OK.
Pete.


#include <octave/oct.h>
#include <malloc.h>
#include <tsDefs.h>
#include <cadef.h>
#include <ezca.h>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;

extern "C" 
{
    extern int ezcaGet(char *pvname, char ezcatype, int nelem, void *data_buff);
    extern int ezcaGetNelem(char *pvname, int *nelem);
    extern int ezcaNewMonitorValue(char *pvname, char ezcatype);
    extern int ezcaClearMonitor(char *pvname, char ezcatype);
    extern int ezcaSetMonitor(char *pvname, char ezcatype);
    extern int ezcaPut(char *pvname, char ezcatype,int nelem, void *data_buff);
    extern int ezcaPvToChid(char *pvname, chid **cid);
    extern  short int ca_field_type ( chid );
    extern  long unsigned int ca_element_count ( chid );
    int Ca_types[7]= {1,2,4,6,0,3,5};

// ezca doesn't treat ENUMs, so fool it and use short, since this is what it resolves to.
#define ezcaEnum 6    

}


DEFUN_DLD(caput, args, ,
	  "caput('pvname',vals). Put values of vals[] to PV 'name'.")
{
     int b=0;
     char pv[255];
     int d,n,i,j,k;
     short int catype;
     int Nelem,Error;
     void *y;
     chid *ch;
     char *y1;
     char *y2;
     int *y3;
     long *y4;
     float *y5;
     double *y6;
     
// Copy data to vector
     if(args.length() >= 3)
     {
        cout << "Only PV name and one value array allowed" << endl;
	return octave_value(0);
	}
     RowVector x(args(1).vector_value());

// space for PV name
     charMatrix c(args(0).string_value());

// Copy name to C array     
     n=args(0).length();
     for (i = 0; i < n; i++) {
     	pv[i]= c(i);
	}
     pv[n]=(char)NULL;

// Get chid of channel
     j=ezcaPvToChid(pv, &ch);

// Use it to get field type     
     catype= Ca_types[ca_field_type(*ch)];

// Get number of elements from channel     
     ezcaGetNelem(pv, &Nelem);

// Allocate memory for C array, copy octave data to it and make the C call, 
// free the C array.
     
     Error=0;
     
     switch(catype){
     	case ezcaString:{
		cout << "Putting string" << endl;
		if (!args(1).is_string()){
			Error=1;
			break;
			}
		n = args(1).length();
		charMatrix y(args(1).string_value());
  		y1=(char *) calloc(n,sizeof(char));
		for(i=0;i<n;i++){
			y1[i]=y(i);
			}
		y1[n]=(char)(NULL);
		d=ezcaPut(pv, ezcaString, 1, (void *)y1);
		free(y1);
		}
		break;
		
	case ezcaByte:
		cout << "Putting bytes" << endl;
		n = args(1).length(); 
		// Check that data lengths match
		if(Nelem != n){
		Error=2;
		break;
		}

		y2=(char *) calloc(n,sizeof(char));
		for (i = 0; i < n; i++) {
			y2[i]= (char) x(i);
			}
		d=ezcaPut(pv,ezcaByte, n, y2);
		free(y2);
		break;
		  		  
	case ezcaShort:
		cout << "Putting shorts" << endl;
		n = args(1).length(); 
		// Check that data lengths match
		if(Nelem != n){
		Error=2;
		break;
		}
		y3=(int *) calloc(n,sizeof(int));
		for (i = 0; i < n; i++) {
			y3[i]= (int) x(i);
			}
		d=ezcaPut(pv, ezcaShort, n, y3);
		free(y3);
		break;

	case ezcaEnum:
		cout << "Putting enum" << endl;
		n = args(1).length(); 
		// Check that data lengths match
		if(Nelem != n){
		Error=2;
		break;
		}
		y3=(int *) calloc(n,sizeof(int));
		for (i = 0; i < n; i++) {
			y3[i]= (int) x(i);
			}
		d=ezcaPut(pv, ezcaShort, n, y3);
		free(y3);
		break;
		
	case ezcaLong:
		cout << "Putting long" << endl;
		n = args(1).length(); 
		// Check that data lengths match
		if(Nelem != n){
		Error=2;
		break;
		}
		y4=(long *) calloc(n,sizeof(long));
		for (i = 0; i < n; i++) {
			y4[i]=(long) x(i);
			}
		
		d=ezcaPut(pv, ezcaLong, n, y4);
		free(y4);
		break;
		
	case ezcaFloat:
		cout << "Putting float" << endl;
		n = args(1).length(); 
		// Check that data lengths match
		if(Nelem != n){
		Error=2;
		break;
		}
		cout << "Lengths OK" << endl;
		y5=(float *) calloc(n,sizeof(float));
		for (i = 0; i < n; i++) {
			y5[i]=(float) x(i);
			}
		
		d=ezcaPut(pv, ezcaFloat, n, y5);
		cout << "Data sent" << endl;
		free(y5);
		cout << "Memory freed" << endl;
		break;
		
	case ezcaDouble:
		cout << "Putting double" << endl;
		n = args(1).length(); 
		// Check that data lengths match
		if(Nelem != n){
		Error=2;
		break;
		}
		cout << "Lengths OK" << endl;
		y6=(double *) calloc(n,sizeof(double));
		for (i = 0; i < n; i++) {
			y6[i]=(double) x(i);
			}
		d=ezcaPut(pv, ezcaDouble, n, y6);
		cout << "Data sent" << endl;
		free(y6);
		cout << "Memory freed" << endl;
		break;
		
	default:
		Error=3;
		break;
	}
	switch(Error){
	case 1:
		cout << "Incorrect variable type" << endl;
		break;
	case 2:
		cout << "Incompatible array lengths" << endl;
		break;
	case 3:
		cout << "Unknown CA type" << endl;
		break;
	default: {}
	}
     if (d != 0) error("caput: Channel Access fault");
     
     return octave_value(Error);
}


DEFUN_DLD(caget, args, ,
	  "caget('pvname'). Get values from  PV 'name'.")
{
     int b=0;
     char pv[255];
     int d,n,i,j,k;
     short int catype;
//     void *y;
     chid *ch;
     char *y1;
     char *y2;
     int *y3;
     long *y4;
     float *y5;
     double *y6;
     octave_value_list answer;
     
     
     charMatrix c(args(0).string_value());
     
// Get PV name into C array
     n=args(0).length();
     for (i = 0; i < n; i++) {
     	pv[i]= c(i);
	}
     pv[n]=(char)NULL;

// Get channel ID so can access structures
     j=ezcaPvToChid(pv, &ch);

// like PV variable type     
     catype= Ca_types[ca_field_type(*ch)];

// Get number of elements in PV     
     ezcaGetNelem(pv, &n);

// Make vector to hold results
     octave_value retval;

// Allocate memory for C array, get data from PV, copy it to Octave vector,
// free up C array.
     switch(catype){

	case ezcaString: {
		  y2=(char *) calloc(256,sizeof(char));
		  d=ezcaGet(pv, catype, n, (void *)y2);
		  n=strlen(y2);
		  string y;
		  for (i = 0; i < n; i++) {
		  	y += (char) y2[i];
			}
		retval=y;
		free(y2);
		}
		break;
		  		  
     	case ezcaByte:{
		  y1=(char *) calloc(n,sizeof(char));
		  d=ezcaGet(pv, catype, n, (void *)y1);
		  RowVector y(n);
		  for (i = 0; i < n; i++) {
		  	y(i)=(char)y1[i];
			}
		retval=y;
		free(y1);
		}
		break;
		
	case ezcaShort: {
		  y3=(int *) calloc(n,sizeof(int));
		  d=ezcaGet(pv, catype, n, (void *)y3);
		  RowVector y(n);
		  for (i = 0; i < n; i++) {
		  	y(i) = (double) y3[i];
			}
		retval=y;
		free(y3);
		}
		break;
		
	case ezcaEnum: {
		  y3=(int *) calloc(n,sizeof(int));
		  d=ezcaGet(pv, ezcaShort, n, (void *)y3);
		  RowVector y(n);
		  for (i = 0; i < n; i++) {
		  	y(i) = (double) y3[i];
			}
		retval=y;
		free(y3);
		}
		break;
		
	case ezcaLong: {
		  y4=(long *) calloc(n,sizeof(long));
		  d=ezcaGet(pv, catype, n, (void *)y4);
		  RowVector y(n);
		  for (i = 0; i < n; i++) {
		  	y(i) = (double) y4[i];
			}
		retval=y;
		free(y4);
		}
		break;
		
	case ezcaFloat: {
		  y5=(float *) calloc(n,sizeof(float));
		  d=ezcaGet(pv, catype, n, (void *)y5);
		  RowVector y(n);
		  for (i = 0; i < n; i++) {
		  	y(i) = (double) y5[i];
			}
		retval=y;
		free(y5);
		}
		break;
		
	case ezcaDouble: {
		y6=(double *) calloc(n,sizeof(double));
		d=ezcaGet(pv, catype, n, (void *)y6);
		RowVector y(n);
		for (i = 0; i < n; i++) {
		    y(i)=y6[i];
		    }
		retval=y;
		free(y6);
		}
		break;
	default:
		cout << "Unknown CA type" << endl;
		return(octave_value(-1));
		break;
	}
	if(d != 0) error("caget: Channel Access fault"); 
     return retval;
}

DEFUN_DLD(cagetnelem, args, ,
	  "cagetnelem('pvname'). Get number of values for PV 'name'.")
{
     char pv[255];
     int n,i,j;
     chid *ch;
     
     
     charMatrix c(args(0).string_value());
     
     n=args(0).length();
     for (i = 0; i < n; i++) {
     	pv[i]= c(i);
	}
     pv[n]=(char)NULL;
     ezcaGetNelem(pv, &n);
     return octave_value(n);
}

DEFUN_DLD(casetmonitor, args, ,
	  "casetmonitor('pvname'). Set a monitor on PV 'name'.")
{
     char pv[255];
     int n,i,j;
     chid *ch;
     
     
     charMatrix c(args(0).string_value());
     
     n=args(0).length();
     for (i = 0; i < n; i++) {
     	pv[i]= c(i);
	}
     pv[n]=(char)NULL;
     j=ezcaPvToChid(pv, &ch);
     n = Ca_types[ca_field_type(*ch)];
     ezcaSetMonitor(pv, (char)n);
     return octave_value(0);
}

DEFUN_DLD(caclrmonitor, args, ,
	  "caclrmonitor('pvname'). Clear a monitor on PV 'name'.")
{
     char pv[255];
     int n,i,j;
     chid *ch;
     
     
     charMatrix c(args(0).string_value());
     
     n=args(0).length();
     for (i = 0; i < n; i++) {
     	pv[i]= c(i);
	}
     pv[n]=(char)NULL;
     j=ezcaPvToChid(pv, &ch);
     n = Ca_types[ca_field_type(*ch)];
     ezcaClearMonitor(pv,(char)n);
     return octave_value(0);
}

DEFUN_DLD(canewmonval, args, ,
	  "canewmonval('pvname'). check for a new value of PV 'name'.\n If no monitors are set, always returns 1, i.e. new data available.")
{
     char pv[255];
     int n,i,j;
     chid *ch;
     octave_value retval;
     
     charMatrix c(args(0).string_value());
     
     n=args(0).length();
     for (i = 0; i < n; i++) {
     	pv[i]= c(i);
	}
     pv[n]=(char)NULL;
     j=ezcaPvToChid(pv, &ch);
     n = Ca_types[ca_field_type(*ch)];
     retval=ezcaNewMonitorValue(pv, (char)n);
     return retval;
}

Navigate by Date:
Prev: RE: vxStats Gurd, Pamela A.
Next: NTP time server problems liushu
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Beam Extracted from SNS Ring Gurd, David P.
Next: NTP time server problems liushu
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Sep 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·