tags:

views:

370

answers:

3

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?

A: 

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?

danbystrom
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
Hiperi0n
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
danbystrom
I got it solved here: http://stackoverflow.com/questions/581682/how-to-create-a-global-handle-in-cVS won't let use new instead of gcnew when using managed code
Hiperi0n
A: 

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.

Jeremy
+1  A: 

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.

m-sharp