Static and non-static method or global class object - forms

I'm making a Windows Forms Application in VS2012 C++.
Situation just for example, real project is more complicated:
I have a Form that contains TextBox, Button and Timer.
Button just triggers the timer. Timer just calls function that increments some variable.
I need to display the function's variable that is incremented, in TextBox.
In Form1.h I add code:
public: void Timer_Function(); //function activated by timer Tick
void Set_Text(String ^str); //function to set TextBox Text
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
if (timer1->Enabled == false) timer1->Enabled = true;
else timer1->Enabled = false;
}
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
Timer_Function();
}
In My_app.cpp code like this:
#include "stdafx.h"
#include "Form1.h"
#include "resource.h"
using namespace test_staticfunc;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew Form1());
return 0;
}
void Form1::Timer_Function()
{
Timer_Func();
}
void Form1::Set_Text(String ^str)
{
textBox1->Text = str;
}
void Timer_Func()
{
static int I=0;
I++;
Form1::Set_Text(I.ToString());
}
Function Timer_Func() is specified in "resource.h" like this:
void Timer_Func();
I.e. I'm trying to display the current state of inner variable I of Timer_Func() by passing it to a Form1 public method Set_Text().
So. The error here is that Set_Text() is not a static method.
I tried to make it static, but got an error "ะก2227: The operand to the left of "->Text" is not a pointer to a class, structure, or union." How to get it right? In that case a static method is trying to implement a non-static method, right?
Or another way: to make an instance of Form1 - instead of
Application::Run(gcnew Form1());
insert code
Form1 ^My_form = gcnew Form1();
Application::Run(My_form);
And use Set_Text as non-static method for class instance My_form.
But My_form is available only in main()! I couldn't make My_form anywhere else. Is there way to make it global or something?
May be there are other ways to solve this problem?
Help, please! I've already searched several forums for answer but didn't find the answer. More precisely non of them suited.
P.S. Sorry for my bad english! ^_^

Related

pthread to invoke member func by wrapping it externally

I'm trying to invoke a member function by pthread by using an external wrapper but it doesn't quite work for me, I get a seg fault. Why is this?
Here's a little test program that displays the problem:
#include <iostream>
#include <pthread.h>
class test {
public:
test();
~test();
void RunTh(void);
private:
pthread_t *pid;
};
void *Run_wrp(void *context);
void test::RunTh(void)
{
while(1);
}
test::test()
{
pthread_create(pid,NULL,&Run_wrp,this);
}
test::~test(){}
int main(void) {
test tmp;
std::cin.get();
}
void *Run_wrp(void *context)
{
((test*)context)->RunTh();
}
Your pid member variable is just a pointer, not an actual pthread_t object.
Change it to:
private:
pthread_t pid;
Then create the new thread with:
pthread_create(&pid,NULL,&Run_wrp,this);
Also, if you want to keep everything contained in the class, you can make your Run_wrp() function a static member function of test, as long as you keep the same signature (return value/arguments). It needs to be static, as non-static functions take the this pointer to the class as a hidden argument, and thus end up with a different signature than what you need for pthread_create().

C++/CLI passing additional arguments to event handling method

I'm trying to write a C++/CLI forms application that creates a lot of buttons at runtime: I have a vector of strings and for each string a button is being created:
std::vector<std::string> strings;
/*
string being initialized with values from file
*/
for ( std::vector<std::string>::iterator it = heroes.begin(); it != heroes.end(); ++it ) {
Button ^ button = gcnew Button;
/*
button being customized depending on the string
*/
buttonPannel->Controls->Add(button);
}
Now what I want to do is add an event handler for each button in a way that the string used to customize the button would be passed to handling method.
In c# I would have written something like
button->Click += new EventHandler((sender, args) => button_Click(s, e, *it));
How do I achieve this in C++/CLI?
You could do the exact equivalent of your C# code, but I'd rather make use of an existing property on the Button class to hold the extra data you need.
In this case, the Tag property seems appropriate: its purpose is to hold any extra data you need that is closely associated with the control, so this seems on-point for your string that drives the program logic. (You may need to make it a managed String^ object, rather than a std::string, but that's an easy conversion.)
void Form1::CreateButtons()
{
for (std::vector<std::string>::iterator it = heroes.begin(); it != heroes.end(); ++it)
{
Button ^ button = gcnew Button;
button->Tag = marshal_as<String^>(*it);
button->Click += gcnew EventHandler(this, &Form1::button_Click);
buttonPanel->Controls->Add(button);
}
}
void Form1::button_Click(Object^ sender, EventArgs^ e)
{
Control^ senderControl = dynamic_cast<Control^>(sender);
String^ heroName = nullptr;
if(senderControl != nullptr)
heroName = dynamic_cast<String^>(senderControl->Tag);
if(heroName == nullptr)
{
// Something went wrong. Bail out.
return;
}
// ...
}
If you really do want to do the equivalent of your C# code: Your C# lambda is doing variable capture on the it variable. We can do variable capture in C++/CLI, it's just a lot more manual.
(Note: Your C# example is capturing the iterator, not the string, not sure if that's what was intended. I wrote this to capture the string object instead.)
ref class EventHandlerStringCapture
{
public:
EventHandlerStringCapture(std::string str,
Action<Object^, EventArgs^, std::string>^ handler)
{
this->str = str;
this->handler = handler;
}
void eventHandler(Object^ sender, EventArgs^ e)
{
this->handler(sender, e, this->str);
}
private:
std::string str;
Func<Object^, EventArgs^, std::string>^ handler;
}
void Form1::CreateButtons()
{
for (std::vector<std::string>::iterator it = heroes.begin(); it != heroes.end(); ++it)
{
Button ^ button = gcnew Button;
// The variable to capture.
std::string str = *it;
// The actual event handler: a method in the current class.
Action<Object^, EventArgs^, std::string>^ actualHandler =
gcnew Action<Object^, EventArgs^, std::string>(this, &Form1::button_Click);
// Pass both the variable to capture and the
// actual event handler to a helper object.
EventHandlerStringCapture^ ehsc =
gcnew EventHandlerStringCapture(str, actualHandler);
// Grab the two-parameter event handler from the helper object,
// and make that the click handler.
button->Click +=
gcnew EventHandler(ehsc, &EventHandlerStringCapture::eventHandler);
buttonPanel->Controls->Add(button);
}
}
void Form1::button_Click(Object^ sender, EventArgs^ e, std::string heroName)
{
// ...
}
(Note: I'm not at a compiler, so there may be syntax errors.)
Obviously, using an existing property on the button object is simpler, but that's the C++/CLI equivalent to what the C# compiler does behind the scenes.

What is the use of callback using function pointer when it can be done in a normal way?

I am new to programming. I was not able to understand the use of call back by function pointer clearly. Please help me to understand where actually the function pointers are needed. I have given two examples. One callback using function pointer and other the normal way(Function calling a function). Forgive me if it appears silly.
#include<stdio.h>
void A()
{
printf("Hello");
}
void B(void(*ptr)())
{
ptr();
}
int main
{
void (*p)() = A;
B(p);
}
Another method
#include<stdio.h>
void A()
{
printf("Hello");
}
void B()
{
A();
}
int main
{
B();
}
What is the use of callback using function pointer when this can be achieved in a simpler way?

Need help to get variable in mfc dialog class

please, I've spent all day trying to figure this out but can't. I have a class (artist1) created from a dialog box with some edit boxes. I want to get the data typed in the edit boxes and save them to variables i made public in the class. But don't know why it doesn't work. PS am new to mfc programming. Thanks
here is my artist class
void artist1::OnBnClickedButton1()
{
//artist1 AA=*art1;
CEdit* pEdit1 = (CEdit*)GetDlgItem(IDC_EDIT1);
pEdit1->GetWindowText(Name1);
nn=new CString;
*nn=Name1;
CEdit* pEdit2 = (CEdit*)GetDlgItem(IDC_EDIT2);
pEdit2->GetWindowText(Age1);
n2=new CString;
*n2=Age1;
CEdit* pEdit3 = (CEdit*)GetDlgItem(IDC_EDIT3);
pEdit3->GetWindowText(Nationality1);
n3=new CString;
*n3=Nationality1;
CEdit* pEdit4 = (CEdit*)GetDlgItem(IDC_EDIT4);
pEdit4->GetWindowText(Group1);
n4=new CString;
*n4=Group1;
CEdit* pEdit5 = (CEdit*)GetDlgItem(IDC_EDIT5);
pEdit5->GetWindowText(num_of_albums1);
n5=new CString;
*n5=num_of_albums1;
SH(Name1,Age1,Nationality1,Group1,num_of_albums1);
art1=this;
// memcpy(art1,this,sizeof(this));
//Name_box.SetWindowText(g);
//AfxMessageBox( Age );
//AfxMessageBox( Nationality );
// TODO: Add your control notification handler code here
}
/*bool artist1::SH()
{
if(NoShow==false)return true;
else return false;
}*/
void artist1::OnBnClickedButton2()
{
//Cooplab1View vm;
NoShow=false;
nvalidateRect(NULL,NULL);
EndDialog(IDD_FORMVIEW);
// TODO: Add your control notification handler code here
}
and here is the class artist header
class artist1 : public CDialogEx
{
//DECLARE_DYNAMIC(artist1)
public:
artist1(CWnd* pParent = NULL); // standard constructor
virtual ~artist1();
bool NoShow;
bool *address;
CString Albums[5];
void OnInsertArtist(artist1 &at);
// Dialog Data
enum { IDD = IDD_FORMVIEW };
private:
CString Nm;
CString Ag;
CString Nation;
CString group;
CString No_of_A;
CString *nnn;
public:
// artist1* GetTreeObj();
//virtual CString ShowDetails(CDC* pDC);
void SH(CString a,CString b,CString c,CString d,CString e)
{
Name=a;
Age=b;
Nationality=c;
Group=d;
num_of_albums=e;
}
protected:
CString Name,Age,Nationality,Group,num_of_albums;
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
CString Name1,Age1,Nationality1,Group1,num_of_albums1;
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
virtual CString ShowDetails(CDC* pDC,artist1 & at1);
afx_msg void OnBnClickedButton2();
};
and i call the class from the CView class cpp file
void Cooplab1View::OnDraw(CDC* pDC)
{
artist1 art;
artist1 A1;
Cooplab1Doc* pDoc = GetDocument();
//ASSERT_VALID(pDoc);
//if (!pDoc)
// return;
if (noShow)
{
art.OnInsertArtist(art);
//art.OnBnClickedButton1();
//art=&obj;
// art.GetTreeObj();
art.ShowDetails(pDC,art);
}
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
}
void Cooplab1View::OnInsertArtist1()
{
noShow=true;
InvalidateRect(NULL,NULL);
//UpdateWindow();
}
You should create variables (right click->Add variables in vs2010) matching your "edit boxes" and check their values.
Don't do "GetDlgItem" and not GetWindowText.
You should addUpdateData(TRUE) at the first line of OnBnClickedButton1
Good Luck !
Your class is quite messy, but if you just want to extract user entry text from the dialog items, it is actually quite simple.
void artist1::OnBnClickedButton1()
{
// Since variables Name,Age,Nationality,Group,num_of_albums are all CString items
// declare as member variables in the class,
// you can just retrieve user entry from the dialog directly into them
// without calling the "SH(Name1,Age1,Nationality1,Group1,num_of_albums1);"
GetDlgItemText(IDC_EDIT1, Name);
GetDlgItemText(IDC_EDIT2, Age);
GetDlgItemText(IDC_EDIT3, Nationality);
GetDlgItemText(IDC_EDIT4, Group);
GetDlgItemText(IDC_EDIT5, num_of_albums);
}
If you are entering a value to the edit control, you should call updatedata( FALSE ). If you want to store the value into a variable then call updatedata(TRUE). That's it.
I finally solved the problem. I declared some global variables, assigned the values inputted in the edit boxes to them in OnBnClickedButton1() using GetDlgItemText then in OnBnClickedButton2() i assigned the global variables to the variables in my class ie Name, Age etc.

C++/CLI class wrapper for c library - callbacks

I am wrapping a C library using C++/CLI. The C library was designed to be used from an unmanaged C++ class. This means that the library functions accept a C++ object pointer and then provide that pointer back in callbacks. This enables the callback code to redirect requests to an appropriate event function in the calling C++ object.
The actual functions are quite involved, so I have simplified the problem space to just a few basic items:
// C library function signature
void CLibFunc(CLIBCALLBACK *callback, void *caller);
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C callback implementation
int CallBackImpl(int param1, void* caller)
{
// Need to call the ManagedCaller's EventFunction from here
// ???
}
// C++/CLI caller class
public ref class ManagedCaller
{
public:
void CallerFunction(void)
{
// Call the C library function
// Need to pass some kind of this class pointer that refers to this object
CLibFunc(CallBackImpl, ????);
}
void EventFunction(param1)
{
}
}
Now the C library functions need to be called from a managed C++ class. Under C++/CLI, the garbage collector moves objects around in memory, so passing a simple fixed pointer to the class does not work anymore. I can solve the problem by pinning the object, but that is not recommended because it leads to memory fragmentation. It seems that another option would be to use auto_gcroot pointers, but I am fairly new to managed C++ an I am not sure how to make this work.
Does anyone know how to make this work? What kind of pointer should be passed to the C function? How should the callback implementation redirect to the calling object's event function?
This just happens to be similar to something I'm in the middle of working on right now.
Here is an blog post on providing native callbacks using C++ classes: http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx
I'm not familiar with calling C++ member functions from C, but I have done an interface (abstract base) class to another C++ class for callbacks (similar to the article). Here is a basic example of what I am providing a bridge for:
// Interface (abstract base) class providing the callback
class IProvider {
public:
virtual ~IProvider() {}
virtual void Callback() = 0;
};
// User class of the callback
class CUser {
IProvider * m_pProvider;
public:
CUser(IProvider * pProvider) {
m_pProvider = pProvider;
}
void DoSomething() {
m_pProvider->Callback();
}
};
// Implementation of the interface class
class CHelloWorldProvider : public IProvider {
void Callback() {
printf("Hello World!");
}
};
// Usage of the callback provider in a pure native setting
void PureNativeUsage() {
CHelloWorldProvider oProvider;
CUser oUser(&oProvider);
oUser.DoSomething();
}
Now in order to make this available for managed implementations of the provider, we have to create a series of classes that provide the bridge.
// Where gcroot is defined
#include <vcclr.h>
// Managed provider interface class
public interface class IManagedProvider {
void Callback();
};
// Native bridge class that can be passed to the user
class CProviderBridge : public IProvider {
// Give the managed class full access
friend ref class ManagedProviderBase;
// Store a reference to the managed object for callback redirects
gcroot<IManagedProvider ^> m_rManaged;
public:
void Callback(){
m_rManaged->Callback();
}
};
// Managed provider base class, this provides a managed base class for extending
public ref class ManagedProviderBase abstract : public IManagedProvider {
// Pointer to the native bridge object
CProviderBridge * m_pNative;
protected:
ManagedProviderBase() {
// Create the native bridge object and set the managed reference
m_pNative = new CProviderBridge();
m_pNative->m_rManaged = this;
}
public:
~ManagedProviderBase() {
delete m_pNative;
}
// Returns a pointer to the native provider object
IProvider * GetProvider() {
return m_pNative;
}
// Makes the deriving class implement the function
virtual void Callback() = 0;
};
// Pure managed provider implementation (this could also be declared in another library and/or in C#/VB.net)
public ref class ManagedHelloWorldProvider : public ManagedProviderBase {
public:
virtual void Callback() override {
Console::Write("Hello World");
}
};
// Usage of the managed provider from the native user
void MixedUsage() {
ManagedHelloWorldProvider ^ rManagedProvider = gcnew ManagedHelloWorldProvider;
CUser oUser(rManagedProvider->GetProvider());
oUser.DoSomething();
}
Edit: Added code to show w/o the managed interface class example I use.
Here is a modified version of my example that can be used given your CLibFunc above. This is assuming how the C function performs the callback is accurate.
Also this might be able to be slimmed down a bit depending on how involved your callback classes are and how much freedom for extension you need.
// Where gcroot is defined
#include <vcclr.h>
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C library function
void CLibFunc(CLIBCALLBACK *callback, void *caller) {
// Do some work
(*callback)(1234, caller);
// Do more work
}
// Managed caller interface class
public interface class IManagedCaller {
void EventFunction(int param1);
};
// C++ native bridge struct
struct CCallerBridge {
// Give the managed class full access
friend ref class ManagedCaller;
// Store a reference to the managed object for callback redirects
gcroot<IManagedCaller ^> m_rManaged;
public:
// Cast the caller to the native bridge and call managed event function
// Note: This must be __stdcall to prevent function call stack corruption
static int __stdcall CallBackImpl(int param1, void * caller) {
CCallerBridge * pCaller = (CCallerBridge *) caller;
pCaller->m_rManaged->EventFunction(param1);
return 0;
}
};
// C++/CLI caller class
public ref class ManagedCaller : public IManagedCaller {
// Pointer to the native bridge object
CCallerBridge * m_pNative;
public:
ManagedCaller() {
// Create the native bridge object and set the managed reference
m_pNative = new CCallerBridge();
m_pNative->m_rManaged = this;
}
~ManagedCaller() {
delete m_pNative;
}
// Calls the C library function
void CallerFunction() {
CLibFunc(CCallerBridge::CallBackImpl, m_pNative);
}
// Managed callback function
virtual void EventFunction(int param1) {
Console::WriteLine(param1);
}
};
// Usage
int main(array<System::String ^> ^args) {
ManagedCaller ^ oCaller = gcnew ManagedCaller();
oCaller->CallerFunction();
return 0;
}