I am trying to compile a custom class in Xcode 3 and I keep getting a no matching function call error although the same custom class compiles fine under Windows. Obviously something is not right regarding the use of curly brackets and the XCode compiler. The compiler is choking at the first curly bracket { below:
: ADataBrowser(inOwnerWindow,inID,inOwner), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
Any ideas much appreciated!
//Full source below
#pragma once
#include <ADataBrowser.h>
#include <AControls.h>
enum
{
kMaxLevelCount = 16
};
class CArray;
class ACustomLabelList :
public ADataBrowser
{
public:
ACustomLabelList(
ControlRef inControl,
bool inOwner = false)
: ADataBrowser(inControl, inOwner), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
ACustomLabelList(
WindowRef inOwnerWindow,
const ControlID &inID,
bool inOwner = false)
: ADataBrowser(inOwnerWindow,inID,inOwner), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
ACustomLabelList(
WindowRef inOwnerWindow,
const Rect &inBounds,
DataBrowserViewStyle inStyle)
: ADataBrowser(inOwnerWindow, inBounds, inStyle), mEncoding(kTextEncodingMacRoman)
{
std::memset( mCustomLabels, 0, sizeof(CFStringRef) * kMaxLevelCount);
}
virtual ~ACustomLabelList();
void Initialize(CArray *inArray, const TextStyle &inStyle);
CFStringRef GetCurrentSelectionLabelString();
void SetCurrentSelectionLabelString(CFStringRef inString);
void SetLabelStringAt(CFStringRef inString, DataBrowserItemID inRowID);
void ShiftCurrentSelectionUp();
void ShiftCurrentSelectionDown();
void SendSelectionChangedEvent();
CFStringRef * GetLabelList() { return mCustomLabels; }
void GetLabelAt(Str15 outString, UInt32 inIndex);
protected:
virtual void ItemNotification(
Item &inItem,
DataBrowserItemNotification inMessage,
ItemData &inItemData);
virtual OSStatus GetItemData(
Item &inItem,
DataBrowserPropertyID inProperty,
ItemData &inItemData);
virtual OSStatus SetItemData(
Item &inItem,
DataBrowserPropertyID inProperty,
ItemData &inItemData);
CFStringRef mCustomLabels[kMaxLevelCount];
TextEncoding mEncoding;
private:
ACustomLabelList(const ACustomLabelList&);
ACustomLabelList& operator=(const ACustomLabelList&);
};
It looks like you're not including the file that declares std::memset.
Related
I have an application with several Forms. Two of them are quite similar, they have features in the form of VCL objects (labels, images, etc...) in common, which I named the same.
I want to have a function in a specific class which can accept one of these two Form as a parameter in order to modify the parameters that they have in common. The solution I came around does not seem to work.
As my application is quite big and complicated, I replicated the problem using a small example.
First, below is an example of my MainForm :
And an example of one subForm (they are all arranged in a similar way)
I have an additionnal class which is used to fill in the Edits on the subForms. The code for this class is the following:
#pragma hdrstop
#include "master_class.h"
#include "sub_Form2.h"
#include "sub_Form3.h"
#include "sub_Form4.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
Master::Master(void)
{
}
Master::~Master(void)
{
}
void Master::WriteToForm(TForm* Form)
{
TForm2* curForm = static_cast<TForm2*>(Form);
TForm3* self = dynamic_cast<TForm3*>(Form);
TForm2* self2 = dynamic_cast<TForm2*>(Form);
if (self != NULL && self2 == NULL) {
TForm3* curForm = static_cast<TForm3*>(Form);
}
else if (self == NULL && self2 != NULL) {
TForm2* curForm = static_cast<TForm2*>(Form);
}
curForm -> Edit1 -> Text = "blablabla_1";
curForm -> Edit2 -> Text = "blablabla_2";
}
And in the MainForm, the code for the "Fill Form2" button is the following:
Master1 -> WriteToForm(Form2);
where Master1 is just an object of the Master class.
This works very well for Form2 :
But for Form3, which is filled up using Master1 -> WriteToForm(Form3), here is what I get, which the same pb than in my real application:
So what should go to the Edit, is misplaced. I think the main pb comes from the fact that I did not create every label, edit, etc... on the same order. I did that on purpose to mimic my real application. To verify this, I created a 3rd subForm, where this time the VCL objects were created in the same order as my first subForm, and this works:
So I would suspect that this comes from the initial cast
TForm2* curForm = static_cast<TForm2*>(Form);
When I pass Form3 as an argument, Form3 is somewhat casted into the "shape" of Form2, which is not defined in the same order. Maybe this could be corrected by modifying directly the DFM file, but it is not a realistic approach for my main app.
I do this initial cast otherwise I get a compilation error saying that curForm is not known at the first line
curForm -> Edit1 -> Text = "blablabla_1";
So, is there a better way to pass the Form as an argument to the WriteToForm function?
Just because two types are similar does not mean they are related. Your code does not work because your two Form classes are not related to each other in any way. You can't just cast one to the other arbitrarily.
To solve this, you have several options:
code for both Form classes separately, eg:
void Master::WriteToForm(TForm* Form)
{
TForm2* curForm2 = dynamic_cast<TForm2*>(Form);
TForm3* curForm3 = dynamic_cast<TForm3*>(Form);
if (curForm2)
{
curForm2->Edit1->Text = _D("blablabla_1");
curForm2->Edit2->Text = _D("blablabla_2");
}
else if (curForm3)
{
curForm3->Edit1->Text = _D("blablabla_1");
curForm3->Edit2->Text = _D("blablabla_2");
}
}
Or:
void WriteToForm(TForm2* Form);
void WriteToForm(TForm3* Form);
...
void Master::WriteToForm(TForm2* Form)
{
Form->Edit1->Text = _D("blablabla_1");
Form->Edit2->Text = _D("blablabla_2");
}
void Master::WriteToForm(TForm3* Form)
{
Form->Edit1->Text = _D("blablabla_1");
Form->Edit2->Text = _D("blablabla_2");
}
Make your function use a template (however, be aware of this: Why can templates only be implemented in the header file?):
template<typename T>
void WriteToForm(T* Form);
...
void Master::WriteToForm<T>(T* Form)
{
Form->Edit1->Text = _D("blablabla_1");
Form->Edit2->Text = _D("blablabla_2");
}
make the two Form classes derive from a common base class or interface, eg:
class TBaseForm : public TForm
{
public:
inline __fastcall TBaseForm(TComponent *Owner) : TForm(Owner) {}
virtual void SetEdit1(const String &Text) = 0;
virtual void SetEdit2(const String &Text) = 0;
};
...
class TForm2 : public TBaseForm
{
...
public:
__fastcall TForm2(TComponent *Owner);
...
void SetEdit1(const String &NewText);
void SetEdit2(const String &NewText);
};
__fastcall TForm2::TForm2(TComponent *Owner)
: TBaseForm(Owner)
{
...
}
void TForm2::SetEdit1(const String &NewText)
{
Edit1->Text = NewText;
}
void TForm2::SetEdit2(const String &NewText)
{
Edit2->Text = NewText;
}
...
repeat for TForm3...
...
void Master::WriteToForm(TBaseForm* Form)
{
Form->SetEdit1(_D("blablabla_1"));
Form->SetEdit2(_D("blablabla_2"));
}
Or:
__interface INTERFACE_UUID("{E900785E-0151-480F-A33A-1F1452A431D2}")
IMyIntf : public IInterface
{
public:
virtual void SetEdit1(const String &Text) = 0;
virtual void SetEdit2(const String &Text) = 0;
};
...
class TForm2 : public TForm, public IMyIntf
{
...
public:
__fastcall TForm2(TComponent *Owner);
...
void SetEdit1(const String &NewText);
void SetEdit2(const String &NewText);
};
__fastcall TForm2::TForm2(TComponent *Owner)
: TForm(Owner)
{
...
}
void TForm2::SetEdit1(const String &NewText)
{
Edit1->Text = NewText;
}
void TForm2::SetEdit2(const String &NewText)
{
Edit2->Text = NewText;
}
...
repeat for TForm3...
...
void Master::WriteToForm(IMyIntf* Intf)
{
Intf->SetEdit1(_D("blablabla_1"));
Intf->SetEdit2(_D("blablabla_2"));
}
use RTTI to access the fields, eg:
#include <System.Rtti.hpp>
void Master::WriteToForm(TForm* Form)
{
TRttiContext Ctx;
TRttiType *FormType = Ctx.GetType(Form->ClassType());
TRttiField *Field = FormType->GetField(_D("Edit1"));
if (Field)
{
TValue value = Field->GetValue(Form);
if( (!value.Empty) && (value.IsObject()) )
{
TObject *Obj = value.AsObject();
// Either:
static_cast<TEdit*>(Obj)->Text = _D("blablabla_1");
// Or:
TRttiProperty *Prop = Ctx.GetType(Obj->ClassType())->GetProperty(_D("Text"));
if (Prop) Prop->SetValue(Obj, String(_D("blablabla_1")));
}
}
Field = FormType->GetField(_D("Edit2"));
if (Field)
{
TValue value = Field->GetValue(Form);
if( (!value.Empty) && (value.IsObject()) )
{
TObject *Obj = value.AsObject();
// Either:
static_cast<TEdit*>(Obj)->Text = _D("blablabla_2");
// Or:
TRttiProperty *Prop = Ctx.GetType(Obj->ClassType())->GetProperty(_D("Text"));
if (Prop) Prop->SetValue(Obj, String(_D("blablabla_2")));
}
}
}
So trying to hook a OpenVR method "ITrackedDeviceServerDriver::GetPose" but i'm getting access violations when my custom hooked method returns out (I think something is wrong with calling convention but idk enough about what x64 asm expects).
All other methods I hook in "ITrackedDeviceServerDriver" work fine. Only "GetPose" fails.
Class thats being hooked looks like:
class ITrackedDeviceServerDriver
{
public:
virtual EVRInitError Activate( uint32_t unObjectId ) = 0;
virtual void Deactivate() = 0;
virtual void EnterStandby() = 0;
virtual void *GetComponent( const char *pchComponentNameAndVersion ) = 0;
virtual void DebugRequest( const char *pchRequest, char *pchResponseBuffer, uint32_t unResponseBufferSize ) = 0;
virtual DriverPose_t GetPose() = 0;
};
Object thats larger than ptr & gets returned from method that crashes
struct DriverPose_t
{
double poseTimeOffset;
vr::HmdQuaternion_t qWorldFromDriverRotation;
double vecWorldFromDriverTranslation[ 3 ];
vr::HmdQuaternion_t qDriverFromHeadRotation;
double vecDriverFromHeadTranslation[ 3 ];
double vecPosition[ 3 ];
double vecVelocity[ 3 ];
double vecAcceleration[ 3 ];
vr::HmdQuaternion_t qRotation;
double vecAngularVelocity[ 3 ];
double vecAngularAcceleration[ 3 ];
ETrackingResult result;
bool poseIsValid;
bool willDriftInYaw;
bool shouldApplyHeadModel;
bool deviceIsConnected;
};
Example of how I'm hooking the virtual methods:
typedef DriverPose_t(__thiscall* GetPose_Org)(ITrackedDeviceServerDriver* thisptr);
GetPose_Org GetPose_Ptr = nullptr;
DriverPose_t __fastcall GetPose_Hook(ITrackedDeviceServerDriver* thisptr)
{
DriverPose_t result = GetPose_Ptr(thisptr);// works
//result.deviceIsConnected = true;
return result;// after return I get access violation crash
}
void TestHook(ITrackedDeviceServerDriver *pDriver)
{
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi, sizeof(MEMORY_BASIC_INFORMATION));
void** vTable = *(void***)(pDriver);
VirtualQuery((LPCVOID)vTable, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);// unlock
Activate_Ptr = (Activate_Org)vTable[0];
vTable[0] = &Activate_Hook;// Hook!
Deactivate_Ptr = (Deactivate_Org)vTable[1];
vTable[1] = &Deactivate_Hook;// Hook!
EnterStandby_Ptr = (EnterStandby_Org)vTable[2];
vTable[2] = &EnterStandby_Hook;// Hook!
GetPose_Ptr = (GetPose_Org)vTable[5];
vTable[5] = &GetPose_Hook;// Hook!
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);// lock
}
So why is "GetPose" the only method that fails after it returns out?
How can I fix the calling convention on "GetPose" to work with registers correctly?
as already noted in comments
__thiscall and __fastcall are not the same calling convention
even for x64. for x86 this is obvious - __thiscall - pass first parameter (this) via Ecx register, and next parameters via stack (i skip now float/double parameters case). __fastcall - 1-first via Ecx, 2-second via Edx, and next via stack
in case x64 (again let assume that no float/double parameters) - first 4 parameters via Rcx, Rdx, R8, R9 and next in stack. so look like x64 have single and common calling convention (no difference between __stdcall, __fastcall, __cdecl, __thiscall)
but exist question about implicit parameters. say in case __thiscall - the first parameter - this is implicit parameter, always passed as first parameter via Ecx/Rcx
and now case when function try "return" object. really on any platform function can return something only via cpu registers. it finite count, and only several of it can be used for return value store.
say on x86(x64) - for return value can be used: AL, AX, EAX, RAX, DAX:EAX, RDX:RAX
so function can return only something that have size - 1, 2, 4, 8 (and 16 for x64)
if function try "return" object with another size - this is impossible do direct, compiler need transform your code. for example if you write function:
DriverPose_t GetPose(ITrackedDeviceServerDriver* thisptr)
{
DriverPose_t pos = ...;
return pos;
}
and call
DriverPose_t pos = GetPose(thisptr);
compiler (of course this already implementation details, different compilers can do this in different ways !) can transform this to
void GetPose(DriverPose_t *ppos, ITrackedDeviceServerDriver* thisptr)
{
DriverPose_t pos = ...;
*ppos = pos;
}
and call to
DriverPose_t pos;
GetPose(&pos, thisptr);
so here pointer to object passed to function as first ,hidden/implicit, parameter. but in case member function, still exist another hidden/implicit, parameter - this, which always passed as first, as result hidden/implicit, parameter for return value moved to second place !
struct ITrackedDeviceServerDriver
{
DriverPose_t GetPose()
{
DriverPose_t pos = ...;
return pos;
}
};
and call
ITrackedDeviceServerDriver obj;
DriverPose_t pos = obj.GetPose();
can be transformed to
struct ITrackedDeviceServerDriver
{
void GetPose(DriverPose_t *ppos)
{
DriverPose_t pos = ...;
*ppos = pos;
}
};
and call to
ITrackedDeviceServerDriver obj;
DriverPose_t pos;
obj.GetPose(&pos);
so real signature of function, if "uncover" this parameter is
void ITrackedDeviceServerDriver::GetPose(ITrackedDeviceServerDriver* this, DriverPose_t *ppos)
{
DriverPose_t pos = ...;
*ppos = pos;
}
and call
ITrackedDeviceServerDriver obj;
DriverPose_t pos;
GetPose(&obj, &pos);
so compare
void ITrackedDeviceServerDriver::GetPose(ITrackedDeviceServerDriver* this, DriverPose_t *ppos);
and
void GetPose(DriverPose_t *ppos, ITrackedDeviceServerDriver* thisptr);
you implement
DriverPose_t GetPose_Hook(ITrackedDeviceServerDriver* thisptr);
which will be transformed by compiler to
void GetPose_Hook(DriverPose_t* ,ITrackedDeviceServerDriver* thisptr);
but really you need implement next hook:
void GetPose_Hook(ITrackedDeviceServerDriver* thisptr, DriverPose_t* );
you confuse first and second parameters. however i think not need change object vtable at all, instead need return proxy object to client. possible and very generic implementation for COM interface hooks, but it too long for post here. for your case can be done next example of hook:
struct DriverPose_t
{
int x, y, z;
};
struct __declspec(novtable) IDemoInterface
{
virtual DriverPose_t GetPose() = 0;
virtual ULONG GetComponent( const char * pchComponentNameAndVersion ) = 0;
virtual void Delete() = 0;
};
class DemoObject : public IDemoInterface
{
ULONG v;
DriverPose_t pos;
virtual DriverPose_t GetPose()
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
return pos;
}
virtual ULONG GetComponent( const char * pchComponentNameAndVersion )
{
DbgPrint("%s<%p>(%s)\n", __FUNCTION__, this, pchComponentNameAndVersion);
return v;
}
virtual void Delete()
{
delete this;
}
public:
DemoObject(ULONG v, int x, int y, int z) : v(v)
{
pos.x = x, pos.y = y, pos.z = z;
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
virtual ~DemoObject()
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
};
class Hook_DemoInterface : public IDemoInterface
{
IDemoInterface* pItf;
virtual DriverPose_t GetPose()
{
DriverPose_t pos = pItf->GetPose();
DbgPrint("%s<%p>=<%d, %d, %d>\n", __FUNCTION__, this, pos.x, pos.y, pos.z);
return pos;
}
virtual ULONG GetComponent( const char * pchComponentNameAndVersion )
{
ULONG v = pItf->GetComponent(pchComponentNameAndVersion);
DbgPrint("%s<%p>(%s)=%u\n", __FUNCTION__, this, pchComponentNameAndVersion);
return v;
}
virtual void Delete()
{
delete this;
}
public:
Hook_DemoInterface(IDemoInterface* pItf) : pItf(pItf)
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
~Hook_DemoInterface()
{
pItf->Delete();
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
};
BOOL CreateDemoIface(IDemoInterface** ppItf)
{
if (DemoObject* pObj = new DemoObject (1, -1, 2, 3))
{
*ppItf = pObj;
return TRUE;
}
return FALSE;
}
BOOL Hook_CreateDemoIface(IDemoInterface** ppItf)
{
IDemoInterface* pItf;
if (CreateDemoIface(&pItf))
{
if (Hook_DemoInterface* pObj = new Hook_DemoInterface(pItf))
{
*ppItf = pObj;
return TRUE;
}
*ppItf = pItf;
return TRUE;
}
return FALSE;
}
void UseIface(IDemoInterface* pItf)
{
ULONG v = pItf->GetComponent("some string");
DriverPose_t pos = pItf->GetPose();
DbgPrint("v=%u, pos<%d, %d, %d>\n", v, pos.x, pos.y, pos.z);
}
void test()
{
IDemoInterface* pItf;
if (CreateDemoIface(&pItf))
{
UseIface(pItf);
pItf->Delete();
}
if (Hook_CreateDemoIface(&pItf))
{
UseIface(pItf);
pItf->Delete();
}
}
instead hook object vtable - hook (if possible) object creation CreateDemoIface - replace it to self Hook_CreateDemoIface which return proxy object.
debug output
DemoObject::DemoObject<0000012C31E08F70>
DemoObject::GetComponent<0000012C31E08F70>(some string)
DemoObject::GetPose<0000012C31E08F70>
v=1, pos<-1, 2, 3>
DemoObject::~DemoObject<0000012C31E08F70>
DemoObject::DemoObject<0000012C31E08F70>
Hook_DemoInterface::Hook_DemoInterface<0000012C31DFAA10>
DemoObject::GetComponent<0000012C31E08F70>(some string)
Hook_DemoInterface::GetComponent<0000012C31DFAA10>(some string)=1
DemoObject::GetPose<0000012C31E08F70>
Hook_DemoInterface::GetPose<0000012C31DFAA10>=<-1, 2, 3>
v=1, pos<-1, 2, 3>
DemoObject::~DemoObject<0000012C31E08F70>
Hook_DemoInterface::~Hook_DemoInterface<0000012C31DFAA10>
I hope someone with knowledge of ROOT's TTreeReader and TVector3 classes can help me out.
I am trying to use TTreeReader to read my TTree which contains a TVector3.
class MuseSelector : public TSelector {
public :
TH1D* h_doca_;
TH1D* h_vertex_z_;
TTreeReader fReader;
TTreeReaderValue<double> mDoca;
TTreeReaderValue<TVector3> mVertex;
MuseSelector(TTree * = 0): mDoca(fReader, "recon_doca"), mVertex(fReader, "recon_vertex") {}
virtual ~MuseSelector() {}
virtual void Init(TTree *tree);
virtual void SlaveBegin(TTree *tree);
virtual Bool_t Process(Long64_t entry);
virtual void Terminate();
virtual Int_t Version() const { return 2; }
ClassDef(MuseSelector,0);
};
void MuseSelector::Init( TTree *tree)
{
fReader.SetTree(tree);
}
void MuseSelector::SlaveBegin(TTree *tree)
{
h_doca_ = new TH1D("h_doca_", "", 100, 0, 100);
h_vertex_z_ = new TH1D("h_vertex_z_", "", 50, -100, 100);
GetOutputList()->Add(h_doca_);
GetOutputList()->Add(h_vertex_z_);
}
Bool_t MuseSelector::Process(Long64_t entry)
{
fReader.SetEntry(entry);
h_doca_->Fill(*mDoca, 1);
h_vertex_z_->Fill((*mVertex)->z(), 1);
return kTRUE;
}
void MuseSelector::Terminate()
{
h_doca_->Print();
h_doca_->Draw();
h_vertex_z_->Draw();
}
I run this class in ROOT with:
TChain *fChain = new TChain("T"); fChain->AddFile("anamuse.root");
fChain->Process("MuseSelector.C");
Where anamuse.root contains a Tree called "T", which contains a TVector3.
I get this error when I run that.
Error in <TTreeReaderValueBase::GetBranchDataType()>: Unknown type and class combination: -1, TVector3
Error in <TTreeReaderValueBase::CreateProxy()>: The branch recon_vertex contains data of type {UNDETERMINED TYPE}, which does not have a dictionary.
Any help would be appreciated. Thank you.
And the conclusion of the discussion at the ROOT forum: that was a bug, it is fixed since a while, e.g. 6.10.08 has that fix. Upgrade ROOT and it will work!
Hi I've been doing gcc plugins for gcc 4.8 and 4.9 but I'm having a problem in gcc 5.1.0. The problem is that I can't register a GIMPLE pass in this new gcc version.
Here is an example plugin code:
int plugin_is_GPL_compatible;
static bool gateCheck(void)
{
printf("BBBBB\n");
return true;
}
static unsigned int executeCheck(void)
{
printf("CCCCC\n");
return 0;
}
const pass_data gimplePass =
{
GIMPLE_PASS, // opt type name
"exampleChecker", // name
OPTGROUP_NONE, // optinfo_flags
TV_NONE, // tv_id
PROP_ssa, // properties_required
0, // properties_provided
0, // properties_destroyed
0, // todo_flags_start
0, // todo_flags_finish
};
class passAttrChecker : public gimple_opt_pass
{
public:
passAttrChecker(gcc::context* ctxt)
: gimple_opt_pass(gimplePass, ctxt)
{}
bool gate (){return gateCheck();}
unsigned int execute(){return executeCheck();}
};
extern int plugin_init(struct plugin_name_args* plugin_info,
struct plugin_gcc_version* version)
{
const char * name = "exampleChecker";
struct register_pass_info pass_info;
pass_info.pass = new passAttrChecker(g);
pass_info.reference_pass_name = "ssa";
pass_info.ref_pass_instance_number = 1;
pass_info.pos_op = PASS_POS_INSERT_AFTER;
register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
return 0;
}
When compiling some file with this plugin should be printed some B's and C's, but nothing is being printed.
The difference with gcc 4.9 is that the type "pass_data" has two less fields than before(has_gate and has_execute). Everything else seems to be like before.
If someone knows what I'm doing wrong or what I'm missing, I'll appreciate the help.
I've already solved it. It was a pretty silly mistake.
Now in gcc 5.1.0 the execute and gate methods from otp_pass recive one argument, instead of void.
This way the example works:
class passAttrChecker : public gimple_opt_pass
{
public:
passAttrChecker(gcc::context* ctxt)
: gimple_opt_pass(gimplePass, ctxt)
{}
bool gate (function *)
{
std::cout << "GATE\n";
return true;
}
unsigned int execute(function *)
{
std::cout << "EXECUTE\n";
return 1;
}
};
DemoI am trying out the c++ bindings shipped with ncurses-5.9. It seems that it is not easy to show a panel with window inside on screen easily. Here is my code
class SpiderApplication : NCursesApplication
{
protected:
int titlesize() const { return 2; };
void title();
public:
SpiderApplication() : NCursesApplication(TRUE) {}
int run();
};
void SpiderApplication::title()
{
const char * const titleText = "Demo";
const int len = ::strlen(titleText);
titleWindow->bkgd(screen_titles());
titleWindow->addstr(0, (titleWindow->cols() - len) / 2, titleText);
titleWindow->noutrefresh();
}
int SpiderApplication::run()
{
NCursesPanel mystd;
NCursesPanel P(mystd.lines() - titlesize(), mystd.cols(), titlesize() - 1, 0);
P.label("Demo", NULL);
P.show();
::getch();
P.clear();
return 0;
}
I suppose that the there should be a panel shown under titleline of this application. However, it doesn't. Do I miss something important here. Is there any example for how to use the c++ binding of ncurses?
Thanks.
I find the answer for my own question.
To make panel shown on screen, refresh() call cannot be omitted. Here is the working code:
NCursesPanel mystd;
NCursesPanel P(mystd.lines() - titlesize(), mystd.cols(), titlesize() - 1, 0);
P.label("Demo", NULL);
P.show();
mystd.refresh();
::getch();
P.clear();