?
Solved

value not being passed

Posted on 2007-10-16
23
Medium Priority
?
284 Views
Last Modified: 2008-01-09
Trouble transferring value of Frame_Rate from one module to another:

thread1.cpp
----------------
...
 void FrameCallBack( TProcessedDataProperty* Attributes, unsigned char* Frameptr )
                                    {

                                        if ( Attributes->CameraID == 1 )
                                        {
                                            blah
                                            blah
                                            Frame_Interval = (Time_Stamp_Now)-(Last_Time_Stamp);
                                            Frame_Rate = (1000/Frame_Interval);
                                            .....
                                   }





mvmfrm.cpp
----------------
extern int Frame_Rate;
....
static int i_Frame_Rate = Frame_Rate;
....
void MVMFrm::WxTimer2Timer1(wxTimerEvent& event)
{
      // insert your code here

   wxClientDC TempDC(WxPanel1);
    TempDC.DestroyClippingRegion();
    wxSize TempSize = TempDC.GetTextExtent(wxString::Format(wxT("%f    "), i_Frame_Rate ));
    TempSize.SetHeight(40);
    TempDC.SetClippingRegion(wxPoint(150,105),TempSize);
    TempDC.Clear();
    TempDC.DestroyClippingRegion();
    TempDC.DrawText(wxString::Format(wxT("%f"), i_Frame_Rate ),wxPoint(150,105));

}

Frame_Rate is coming out as "0000000", yet its non-zero in the thread. How do I transfer the value successfully from one module to another.

WLE
0
Comment
Question by:Wanderinglazyeye
  • 14
  • 8
23 Comments
 
LVL 14

Expert Comment

by:wayside
ID: 20089461
> static int i_Frame_Rate = Frame_Rate;

This happens only once when the program is initialized. After that, changes to Frame_Rate do not affect i_Frame_Rate.

You can add a line in your function to update i_Frame_Rate:

i_Frame_Rate = Frame_Rate;

or just use Frame_Rate directly

or use a pointer:

static int *p_i_Frame_Rate = &Frame_Rate;

...

wxSize TempSize = TempDC.GetTextExtent(wxString::Format(wxT("%f    "), *p_
i_Frame_Rate ));

etc.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20091912
Or simply drop the i_Frame_Rate and use Frame_Rate

wxSize TempSize = TempDC.GetTextExtent(wxString::Format(wxT("%f    "), Frame_Rate ));

Regards, Alex
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20091944
>>>> extern int Frame_Rate;

instead of making it an extern variable you may consider to make it a static member of the class you are dealing with, e. g. the MVMFrm class

class  MVMFrm  : ....
{
    ...
public:
    int Frame_Rate;  

    ...
};


// mvmfrm.cpp

#include "mvmfrm.h"
 
    int MVMFrm::Frame_Rate = 50;  // some initial value


With that you can use it like

      MVMFrm::Frame_Rate = (1000/Frame_Interval);

or

     wxSize TempSize = TempDC.GetTextExtent(wxString::Format
                                                (wxT("%f    "), MVMFrm::Frame_Rate ));


You also could make it a static member function:

class  MVMFrm  : ....
{
    ...
public:
    int& Frame_Rate() { static int fr = 0; return fr; }  

    ...
};

and use it like

      MVMFrm::Frame_Rate() = (1000/Frame_Interval);  // note the ()

or

     wxSize TempSize = TempDC.GetTextExtent(wxString::Format
                                                (wxT("%f    "), MVMFrm::Frame_Rate() ));



0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20091961
Global variables is the C way to share variables between modules. In C++ you should avoid using globally defined variables or functions beside you have both C++ and C modules.
0
 

Author Comment

by:Wanderinglazyeye
ID: 20093448
I took the approach of the static member function. Got an error (below)

MVMFrm.h
---------------
public:
        int& Frame_Rate() { static int fr = 0; return fr; }

MVMFrm.cpp
--------------
void MVMFrm::WxTimer2Timer1(wxTimerEvent& event)
{
      // insert your code here

      wxClientDC TempDC(WxPanel1);
    TempDC.DestroyClippingRegion();
    wxSize TempSize = TempDC.GetTextExtent(wxString::Format(wxT("%f    "), MVMFrm::Frame_Rate()  ));
    TempSize.SetHeight(40);
    TempDC.SetClippingRegion(wxPoint(150,105),TempSize);
    TempDC.Clear();
    TempDC.DestroyClippingRegion();
    TempDC.DrawText(wxString::Format(wxT("%f"), MVMFrm::Frame_Rate()  ),wxPoint(150,105));
}

Thread1.cpp
---------------
#include "MVMFrm.h"

MVMFrm::Frame_Rate()=Frame_Rate_i; //<----------------Thread1.cpp [Error C2352] 'MVMFrm::Frame_Rate' : illegal call of non-static member function

WLE


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20093495
>>>>        int& Frame_Rate() { static int fr = 0; return fr; }
sorry, you have to add keyword 'static' for a static member function ;-)    

   static int& Frame_Rate() { static int fr = 0; return fr; }
0
 

Author Comment

by:Wanderinglazyeye
ID: 20094277
Now its working without errors. The variable is definitely working in my thread. The FPS is around 41. But in my GUI, the argument is still appearing as zero when referenced in my timer snippet above in MVMFrm. No errors, but zero value. The GUI value should be the same as the thread value. I have checked the routine to make sure it is being called and it is - every 100ms.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20094569
>>>> The variable is definitely working in my thread
Is the thread running in a different executable? In a dll? If yes, you should use a class that was defined solely in the dll and which exports its interface (using either __declspec(dllexport) or __declspec(dllimport)  specifier depending on which project was built).

If not exporting the class, each project has it's own static class members and you can't share the data.  
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20094643
>>>> use a class that was defined solely in the dll

#ifndef SHARED_H
#define SHARED_H

#   ifdef DLL_PROJECT
#       define  EXPIMP_SPEC __declspec(dllexport)
#   else
#       define  EXPIMP_SPEC __declspec(dllimport)
#   endif

EXPIMP_SPEC class Shared
{
public:
      static int& Frame_Rate() { static int fr = 0; return fr; }
     
};

#endif

if including that header both in the dll (thread) and the GUI (application) project and set the DLL_PROJECT preprocessor macro for the dll project only, you should be able to set the frame rate by

    Shared::Frame_Rate() = 50;

in either module and read the result by

   int frame_rate = Shared::Frame_Rate();

with reading the current value. Be aware that it is only one variable and that it should be initialized only in the static function itself or - better said - do not initialize it more than once by accident.
0
 

Author Comment

by:Wanderinglazyeye
ID: 20094842
Ok, that worked pretty well (compiled without error) until I set the value in my MVMFrm.cpp:

Shared::Frame_Rate() = 50;

MVMFrm.cpp [Error C2761] 'int &Shared::Frame_Rate(void)' : member function redeclaration not allowed

Its only initialized once there. Did I miss a step? Do I need to change anything in my project properties?



0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20095114
>>>> static int& Frame_Rate() { static int fr = 0; return fr; }

Seems as you couldn't do it with inlining. Put the implementation of the static function to shared.cpp and add the shared.cpp to the dll project only. The application project will get the module when importing the dll functions. In the moment you still have duplicate code because of the inline implementation in the header file
(which I made for simplicity reasons only but it was wrong).
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20095244
>>>> MVMFrm.cpp [Error C2761] 'int &Shared::Frame_Rate(void)'

Hmmm. I wonder why the compiler complained. The C2761 is for 'multiple declarations' of class members:

class X
{
       void f(int i
};

// somewhere else
#include "x.h"

    void X::f();  // C2761


So, maybe the error is cause the compiler interpreted a calling as a declaration.

    Shared::Frame_Rate() = 50;

(what would be strange but is not quite impossible).
If I am right you would have to change the statement to

    int& fr = Shared::Frame_Rate();  // create a temporary reference
    fr = 50;  // set the value

so it can't be mixed up with a declaration.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20095282
Note, the shared.cpp is necessary regardless whether it solves the C2761 or not. If making inlining the app and the dll will have their own 'static' implementation. You have to achieve that the dll 'provides' a module and *not* that each executable gets its own 'copy' via the header file.
0
 

Author Comment

by:Wanderinglazyeye
ID: 20097516
I made the change recommended above:

int& fr = Shared::Frame_Rate();  // create a temporary reference
fr = 50;  // set the value

Now, I get this error( the other one stopped):

 [Error C4430] missing type specifier - int assumed. Note: C++ does not support default-int

[Error C2040] 'fr' : 'int' differs in levels of indirection from 'int &'

I think we're making headway. ...
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20099003
>>>> [Error C4430] missing type specifier - int assumed.
>>>> Note: C++ does not support default-int

The compiler still could not recognize the (right-side) Shared::Frame_Rate() as a known function. That's why it 'assumed' int as a return value. And with that assumption int and int& have different level of 'indirection'.

Is that error in the dll or in the app?
Is somewhere a .c file involved?
Did you switch off 'precompiled header'?
Did you include the shared.h?

Can you post both shared.h and the source where the compiler errors occur?

0
 

Author Comment

by:Wanderinglazyeye
ID: 20101584
shared.h is included
error is in the app, line marked below
there are C code modules called from the thead1.cpp (opencv)
I don't see an option in the complier settings that refers to precompiled header

Here are is the code:

MVMFrm.cpp
-----------------
#include "MVMFrm.h"
#include "CameraAPI.h"
#include "BUF_USBCamera_SDK.h"
#include "shared.h"
#include "LUT.h"
#include "OpenCVThread1.h"
#include "Calibrate2Frm.h"
#include "Status.h"
#include "highgui.h"
#include "cv.h"
#include "cvaux.h"
#include "wx/thread.h"


#include <wx/msw/private.h>
#include <iostream>

using namespace std;
//flags
#define TOGGLE_ON  1
#define TOGGLE_OFF 0
#define TOGGLEFR_ON  1
#define TOGGLEFR_OFF 0
#define TOGGLEFF_ON 1
#define TOGGLEFF_OFF 0
#define STATUS_IC_ON  1
#define STATUS_IC_OFF 0
#define FLIPFLOP_ON 1
#define FLIPFLOP_OFF 0

static int iToggleFlag = TOGGLE_OFF; //initial state should be OFF
static int iToggleFlagFR = TOGGLEFR_OFF; //initial state should be OFF
static int iToggleFlagFF = TOGGLEFF_OFF;
static int IC_ToggleFlag = STATUS_IC_OFF; // initial state should be off
static int Toggle_FlipFlop = FLIPFLOP_OFF;
static bool show_position = false;
static bool show_frame_rate = false;
static bool Flash   = false;
static bool Flash2  = false;
static bool Flash3  = false;
static bool Flash4  = false;
static bool Flash5  = false;
static bool Flash6  = false;
static bool Flash7  = false;

int& fr = Shared::Frame_Rate();  // create a temporary reference
fr = 50;  // set the value    <---------------------------------------------------------BOTH ERRORS this line
...
void MVMFrm::WxTimer2Timer1(wxTimerEvent& event)
{
      // insert your code here

      wxClientDC TempDC(WxPanel1);
    TempDC.DestroyClippingRegion();
    wxSize TempSize = TempDC.GetTextExtent(wxString::Format(wxT("%f    "), MVMFrm::Frame_Rate()  ));
    TempSize.SetHeight(40);
    TempDC.SetClippingRegion(wxPoint(150,105),TempSize);
    TempDC.Clear();
    TempDC.DestroyClippingRegion();
    TempDC.DrawText(wxString::Format(wxT("%f"), MVMFrm::Frame_Rate()  ),wxPoint(150,105));
}

shared.h
--------------
#ifndef SHARED_H
#define SHARED_H

#   ifdef DLL_PROJECT
#       define  EXPIMP_SPEC __declspec(dllexport)
#   else
#       define  EXPIMP_SPEC __declspec(dllimport)
#   endif

EXPIMP_SPEC class Shared
{
public:
      static int& Frame_Rate() { static int fr = 0; return fr; }

};

#endif
0
 

Author Comment

by:Wanderinglazyeye
ID: 20101615
Left out one error I didn't see sorry...

shared.h [Warning C4091] '__declspec(dllimport)' : ignored on left of 'Shared' when no variable is declared

#ifndef SHARED_H
#define SHARED_H

#   ifdef DLL_PROJECT
#       define  EXPIMP_SPEC __declspec(dllexport)
#   else
#       define  EXPIMP_SPEC __declspec(dllimport)
#   endif

EXPIMP_SPEC class Shared
{
public:
      static int& Frame_Rate() { static int fr = 0; return fr; }

};<-------------------ERROR HERE

#endif
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20101888
ok.

1. The last warning most likely is the most important as it seems that the class interface actually wasn't exported because of that.

You may define a dummy member to solve that.

EXPIMP_SPEC class Shared
{
      int dummy;
public:
      static int& Frame_Rate() { static int fr = 0; return fr; }

};

2. { static int fr = 0; return fr; } the implementation you should put to a shared.cpp
 
// shared.cpp
#include "shared.h"
int& Shared::Frame_Rate()
{
    static int fr = 0;
    return fr;
}

3. EXPIMP_SPEC class Shared

I checked my own sources for exported classes and it turned out that the export/import specifier should (must?) be between the keyword class and the 'classname'.

    class EXPIMP_SPEC Shared

4. If it doesn't compile/work nevertheless you might consider using a different filename than 'shared.h' (or check whether you have more than one shared.h).

Regards, Alex









0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 2000 total points
ID: 20102041
I tested the above with an exported function in a dll and it worked at first approach:

I could set

   VwsFieldEntry::shared() = 100;  

in my app  (VwsFieldEntry is an exported class of a dll) and debugged into a dll function where I read the value with

   int n = VwsFieldEntry::shared();

and it was ok.

VwsFieldEntry::shared() was implemented like

int& VwsFieldEntry::shared()
{
    static int i = 0;
    return i;
}

The class was declared like

class EXPIMP_SPEC VwsFieldEntry
{
    char*  pszLabel;
    char*  pszValue;
    VwsFieldEntry() : pszLabel(NULL), pszValue(NULL) {}
    ....
public:
    static int& shared();
};
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20102142
It also worked without warning/errors when defining the class like

class EXPIMP_SPEC Shared
{
public:
    static int& shared();
};

So, the dummy member can be omitted.
0
 

Author Comment

by:Wanderinglazyeye
ID: 20116529
Thanks Alex, some very fine help. Here is another solution, though not as interesting or as elegant as your approach. I added two members to my camera operations class (StartMachineVision) and created two functions. The first stores any integer passed to it; if a false is passed, it simply returns the stored number. This  helped with frame intervals that were old and had to be stored for subtraction from the current frame interval. The second function stored the frame rate, and if false was passed to it, it simply returned the frame rate, accessible in any other part o the program. Worked fine.

Here's what I did:

MachineVisionMod.h
----------------------------
class StartMachineVision
{


private:
public:
    StartMachineVision();
     ~StartMachineVision();
bool Init_Camera();
bool Start_Tracking();
bool Shutdown();

int Last_Frame_Stamp(bool, int);
  int Stored_Frame_Value;
  int Stored_Value_Return_Val;

int Frame_Rate_Stored( bool, int);
  int Stored_Frame_Rate_Value;
  int Frame_Rate_Stored_Value_Return_Val;

};

MachineVisionMod.cpp
---------------------------
void FrameCallBack( TProcessedDataProperty* Attributes, unsigned char* Frameptr )
                                    {
extern StartMachineVision StartMachineVisionInst;

Last_Time_Stamp = StartMachineVisionInst.Last_Frame_Stamp( false, 1);
                                        Frame_Interval = (Time_Stamp_Now)-(Last_Time_Stamp);
                                        Frame_Rate = (1000/Frame_Interval);
                                        Last_Time_Stamp = Time_Stamp_Now;
                                        StartMachineVisionInst.Last_Frame_Stamp( true, Last_Time_Stamp);
                                        StartMachineVisionInst.Frame_Rate_Stored( true, Frame_Rate);
...
}


MVMFrm.cpp (my GUI)
-----------------------------
void MVMFrm::WxTimer2Timer1(wxTimerEvent& event)
{
      // insert your code here
    int Frame_Rate_Temp = StartMachineVisionInst.Frame_Rate_Stored( false, 1);
      wxClientDC TempDC(WxPanel1);
    TempDC.DestroyClippingRegion();
    wxSize TempSize = TempDC.GetTextExtent(wxString::Format(wxT("%d    "), Frame_Rate_Temp  ));
    TempSize.SetHeight(40);
    TempDC.SetClippingRegion(wxPoint(150,105),TempSize);
    TempDC.Clear();
    TempDC.DestroyClippingRegion();
    TempDC.DrawText(wxString::Format(wxT("%d"), Frame_Rate_Temp ),wxPoint(150,105));
}


Works well...But like I said, yours is a TOB - thing of beauty...
WLE
0
 

Author Comment

by:Wanderinglazyeye
ID: 20116533
Left out in MVMFrm.cpp, class was instantiated as such:

StartMachineVision StartMachineVisionInst;


--WLE
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20117745
>>>> extern StartMachineVision StartMachineVisionInst;

Yes, defining global variables and refering to it via extern keyword is a valid solution both for C and C++. And it has the advantage that it is working for multiple executables as well where static class members would create multiple instances (what would lead to severe problems if objects needs to be shared between the executables.

Nevertheless, global variables as a concept should be used in C++ for singleton class instances only, e. g.

// the one and only thread manager
extern ThreadManager theThreadManager;

while for sharing data you either call such a shared manager, e. g.

    int framerate = theManager.getCurrentFrameRate();

or use a exported static class member function with statically stored data as I showed above.

Regards, Alex
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Navigation is an important part of web design from a usability perspective. But it is often a pain when it comes to a developer’s perspective. By navigation, it often means menuing. This is less theory and more practical of how to get a specific gro…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
Suggested Courses
Course of the Month14 days, 7 hours left to enroll

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question