Friday, April 8, 2011

C# form in a C++ program

Hello. In my last question I asked about running a C# form in a C++ program. I got it working, but I am having problems. I will try to be brief.

My C++ program must execute a C# form and execute some simple functions in it (increasing counters and showing them). However I do not know the best way to do this. I have the form initialized in an init function:

C++

SUTAdapter::Form1^ *ptForm1; // Global variable

...

FormProject::Form1^ form1;
form1 = gcnew FormProject::Form1();
ptForm1 = &form1;
(*ptForm1)->Show();
(*ptForm1)->incCounter(0);

Some other functions in the C++ program just call incCounter. My problem is, that a second call from another function to incCounter makes my C# Form1 null (this == null), so I can use the function code of incCounter but not the class variables. It is strange, as if the program disposed the FormProject.

C#

public void incCounter(int counter)
{
  int param1 = counter;
  this.count[counter]++; // this == null in sucessive calls from c++ program
}

What am I doing wrong? I have actually disabled the form and just using the function and variables in case the problem is with the UI (invoke and so). Is exiting the C++ init function (the first chunk of code) clearing the Form1?

From stackoverflow
  • My guess would be that *ptForm1 isn't sufficient to make the CLR count it as a reference. Maybe it should be Form1^^ ptForm, instead? Or why aren't you just putting the form1 variable as you global insted of a pointer?

    Hiperi0n : It won't let me having a handle to a handle, just a pointer to a handle. I have it so I can call tha form's functions from other functions
    Hiperi0n : Also, it won't let me have handles as global variables, weird but this is the only way I got it to work
    danbystrom : Then my guess is that as soon as form1 goes out of scope, the GC will dispose of it. What about doing new instead and then manually delete it? Actually I haven't done this myself, but chances are that I will have to do it in near time, so I'm interested to know what you find out! :-)
    danbystrom : Of interest? http://blogs.msdn.com/hsutter/archive/2003/12/05/53522.aspx
    Hiperi0n : I got it solved here: http://stackoverflow.com/questions/581682/how-to-create-a-global-handle-in-c VS won't let use new instead of gcnew when using managed code
  • I think you should just be storing the handle in a global (i.e. static) object, or at least a static field of a convenient class to use. Like danbystrom said, keeping a pointer to the Form reference will not prevent the garbage collector from reclaiming the form once the original handle goes null.

    static ref class Globals
    {
        static FormProject::Form1^ MyForm;
    }
    
    // Later on...
    Globals::MyForm = form1;
    form1->DoStuff();
    form1 = nullptr;
    
    // Globals::MyForms still exists!
    

    Though I suspect the Form reference going null means something else is wrong too.

  • If you must take the address of a .NET object on the managed heap, put it in a pin_ptr<> so that the GC does not move it. That could be the source of your problem.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.