Knyta upp sig mot databasen och hantera objekt och data
Vi börjar med att skriva ett enkelt c++ program som knyter upp sig mot realtidsdatabasen och
länkar sig mot några objekt.
cpp-filen bör ligga på $pwrp_src katalogen, eller på på någon underkatalog till denna. Vi skapar
katalogen $pwrp_src/myappl och editerar filen ra_myappl.cpp.
Datatyper
I include-filen pwr.h finns de grundläggande datatyperna i ProviewR definierade. De vanligaste
är pwr_tBoolean som används för digitala signaler och pwr_tFloat32 för analoga signaler, men
där finns även c-typer för alla andra ProviewR-typer, t ex pwr_tInt32, pwr_tUInt32, pwr_tString80
etc.
Initiering av gdh
Uppknytningen mot databasen görs med anropet gdh_Init() där man skickar med en sträng som
identifierar applikationen. Först inkluderar vi pwr.h som innehåller grundtyperna i ProviewR
och rt_gdh.h som innehåller grånssnittet mot realtidsdatabasen.
#include "pwr.h"
#include "rt_gdh.h"
int main() {
pwr_tStatus sts;
sts = gdh_Init( "ra_myappl");
if ( EVEN(sts)) {
cout << "gdh_Init failure " << sts << endl;
exit(0);
}
}
Funktionen returnerar en status variabel av typen pwr_tStatus. En jämn status innebär att
något är fel, udda att anropet gick bra. Status kan även översättas till en sträng som ger
mer information om vad som är fel, vilket beskrivs närmare längre fram.
Läsa och skriva värden
Om vi vill skriva och läsa ett attribut i ett objekt kan man använda funktionerna
gdh_SetObjectInfo() och gdh_GetObjectInfo().
En läsning resp skrivning av Dv'n H1-H2-Start kan se ut så här. Notera att värdet av Dv'n
ligger i attributet ActualValue
pwr_tBoolean value;
sts = gdh_GetObjectInfo( "H1-H2-Start.ActualValue", &value, sizeof(value));
if (ODD(sts)) {
value = !value;
sts = gdh_SetObjectInfo( "H1-H2-Start.ActualValue", &value, sizeof(value));
}
Direktlänka mot attribut
Ofta är ligger applikationsprogram i en oändlig loop och övervakar attribut i databasen
och reagerar på vissa förändringar. Då är det bättre att direktlänka sig mot attributet,
dvs skaffa en pekare. Det gör man med gdh_RefObjectInfo(). Ofta delar man upp programmet
i en init() funktion som direktlänkar till attribut, en scan() funktion som som
innehåller övervakning och styrfunktioner, och en close() funktion tar ner direktlänkningarna.
class ra_myappl {
pwr_tBoolean *start_ptr;
pwr_tRefId dlid;
public:
ra_myappl() {}
void init();
void scan();
void close();
};
void ra_myappl::init()
{
sts = gdh_RefObectInfo( "H1-H2-Start.ActualValue", &start_ptr, &dlid,
sizeof(*start_ptr));
if ( EVEN(sts)) exit(0);
}
void ra_myappl::scan()
{
for (;;) {
if ( *start_ptr) {
// Do something...
cout << "Starting" << endl;
*start_ptr = 0;
}
sleep(1);
}
}
void ra_myappl::close()
{
gdh_UnrefObjectInfo( &dlid);
}
I init() funktionen fylls pekaren start_ptr i så att den pekar på värdet för Dv'n H1-H2-Start
i databasen.
Varning !
Notera att pekare i c kräver varsam hantering. Om man använder pekar-aritmetik eller indexerar
i vektorer är det lätt hänt att man pekar fel och skriver på fel ställe i databasen. Detta kan
ge upphov till fel som är svåra att hitta orsaken till.
Direktlänka mot objekt
gdh_RefObjectInfo() kan förutom att direktlänka mot enskilda attribut, också direklänka mot
objekt och attributobjekt.
Antag att vi vill fylla i punkter i en kurva och visa upp i en bild. Vi vill direktlänka till
objektet H1-H2-Curve som är av klassen XyCurve. Includefilen pwr_baseclasses.hpp innehåller
en c++ klass, pwr_Class_XyCurve, för objektet.
#include
#include "pwr.h"
#include "pwr_baseclasses.hpp"
#include "rt_gdh.h"
class ra_myappl {
pwr_Class_XyCurve *curve_ptr;
pwr_tRefId dlid;
public:
ra_myappl() {}
void init();
void scan();
void close();
};
void ra_myappl::init()
{
pwr_tStatus sts;
pwr_tOName name = "H1-H2-Curve";
// Connect to database
sts = gdh_Init( "ra_myappl");
if ( EVEN(sts)) exit(0);
// Direct link to curve object
sts = gdh_RefObjectInfo( name, (void **)&curve_ptr, &dlid, sizeof(*curve_ptr));
if ( EVEN(sts)) exit(0);
}
void ra_myappl::scan()
{
for ( unsigned int i = 0;;i++) {
if ( i % 5 == 0) {
// Calculate x and y coordinates for a sine curve every fifth second
for ( int j = 0; j < 100; j++) {
curve_ptr->XValue[j] = j;
curve_ptr->YValue[j] = 50 + 50 * sin( 2.0 * M_PI * (j + i) / 100);
}
// Indicate new curve to graph
curve_ptr->Update = 1;
}
else if ( i % 5 == 2)
curve_ptr->Update = 0;
sleep(1);
if ( i > 360)
i = 0;
}
}
void ra_myappl::close()
{
gdh_UnrefObjectInfo( dlid);
}
int main()
{
ra_myappl myappl;
myappl.init();
myappl.scan();
myappl.close();
}
Programmet kompileras och länkas med
> g++ -g -c ra_myappl.cpp -o $pwrp_obj/ra_myappl.o -I$pwr_inc -DOS_LINUX=1
-DOS=linux -DHW_X86=1 -DHW=x86
> g++ -g -o $pwrp_exe/ra_myappl $pwrp_obj/ra_myappl.o $pwr_obj/pwr_msg_rt.o
-L$pwr_lib -lpwr_rt -lpwr_co -lpwr_msg_dummy -lrt
Senare ska vi se hur man använder make för att kompilera och länka.
Om vi öppnar objektsbilden för H1-H2-Curve objektet kan vi studera resultatet.

Fig Objektbild for kurvobjektet