如何在C ++ / CLI类中保留对托管对象的引用 [英] How do I keep reference to managed object in a C++/CLI class

查看:59
本文介绍了如何在C ++ / CLI类中保留对托管对象的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以这是设置。我有一个用C ++编写的大型遗留代码库,并使用了大量的MFC。我创建了一个新的页面/类,需要使用C#表单。使用VS2010

*我能够使用/ clr标志编译单个新类。

*我能够在我的解决方案中添加一个简单的C#项目并在通话期间使用它。



问题是:我如何在我的C ++代码中保留这个C#对象的句柄。我意识到我的托管对象引用需要驻留在类定义中,但是我遇到了将它放入标题的问题。我可能误解了一些基本的C ++ / CLI概念。



我试图重构尽可能少的遗留代码。这就是我使用选项将单个文件/类设置为使用/ clr编译的原因。我知道标题实际上没有编译,这就是为什么没有编译选项。这使我无法添加系统参考



请参阅下面的示例以供参考。



  //   Setup.h  
#include stdafx.h
/ * 不喜欢这些
使用命名空间系统;
使用命名空间TestCSharpForm;
使用命名空间System :: Windows :: Forms;
* /

class SetupPage: public Page
{
public
void activate();
void deActivate();

SetupPage(Page * pParent = NULL);
virtual ~SetupPage();
受保护
虚拟 void DoDataExchange(CDataExchange * pDX);

private
// TestCSharpForm :: myForm ^ myCSharpForm;
};
// END Setup.h



  //   Setup.cpp  
使用 命名空间系统;
使用 命名空间 System :: Windows :: Forms;
使用 命名空间 TestCSharpForm;

SetupPage :: SetupPage(GLTreePage * pParent):Page(UITreeWizard_InspectionSetup :: IDD,pParent)
{
// 我没有要创建的TestCSharpForm的成员定义
}


SetupPage :: ~AdminPage()
{
clear();
}

// 这有效,我可以在本地访问该对象activate()
void SetupPage :: activate()
{
TestCSharpForm :: myForm ^ myCSharpForm = gcnew TestCSharpForm :: myForm();
}





提前感谢任何人提供解决方案或正确方向的观点。如果我能提供任何澄清,请告诉我。

解决方案

试试这个:



快速又脏又脏。如果您的表单可以作为单例生存(任何时候只能生成一次),请在Setup.cpp中将其声明为静态。它不漂亮,但应该工作。但是,我建议将托管代码和非托管代码分开。



更好:你已经有了一个MFC项目EXE,你为这个新UI添加了一个C#项目加成。为您的C ++ / CLI代码创建第三个项目。这将是.NET和本机代码之间的垫片。您不需要Active-X控件(您可以,但它更多的工作)。最终会得到两个程序集和一个EXE。



C ++ / CLI程序集可以导出所需的内容,以便您的MFC应用程序可以传递参数并获取结果。也可以在CLI包装器中具有本机回调函数,以响应在C#程序集中触发的委托。



您必须将C ++ / CLI限制为仅包含在本机C ++中有效的类型。这意味着将C#字符串转换为MFC CStrings或STL std :: strings。



通常,尽可能减少CLI包装器中的代码量。 .NET可以在C#程序集中工作吗?本地工作在MFC应用程序中。



不要忘记打开混合调试,这样你就可以进入/退出祝你在调试器中管理与非托管代码。



祝你好运。


请看我对这个问题的评论。 />


首先, #includestdafx.h不像使用,甚至不是关闭。这只是包含文件,在CLI中通常不需要,只是C ++特定的东西。



使用也没什么特别的。这与非托管C ++使用完全一样。它什么都不做,只引入缩短的类型名称。例如,您可以使用 System :: Windows :: Forms :: Form 而不使用任何using,或者您可以使用System :: Windows使用 :: Forms ,这将允许您使用表单而不使用上面提到的完整类型名称...



我不知道还有什么不清楚。



-SA


< blockquote>虽然您的问题不明确,但如果您需要在本机类中保留托管类型的句柄,则以下内容可能会有用。



如何:在本机类型中声明句柄 [ ^ ]



如果只有一些文件被打包作为托管,通常你会使用2个不同的预编译头文件或仅将它们用于本机代码文件(那些没有/ clr选项编译的文件)。



甚至虽然我做了混合模式编程,在我的情况下管理所有接口。如果表单像对话框一样使用,那么从你的应用程序中使用它们应该不难,但是你可能想要为了所有权目的而实现IWin32Window接口...



否则,如果要在MFC对话框中使用UI,那么我认为它应该是托管端的用户控件(最好使用C#),它们可能应该作为Active / X控件导出。我没有经验,但使用谷歌,你应该能够做到这一点。以下是搜索的最佳结果使用c#用户控件作为activex



http://www.codeguru .com / csharp / .net / net_general / comcom / article.php / c16257 / Create-an-ActiveX-using-a-Csharp-Usercontrol.htm [ ^ ]



http://www.telerik.com/support/kb/winforms/details/wrapping-a-net-user-control-as-an-activex [ ^ ]



http://stackoverflow.com/questions/7409433/expose-a-winforms-usercontrol-as-an-activex-control [ ^ ]



如果要创建的页面类要在任何MFC页面未使用的独立对话框中使用,那么在这种情况下,我认为它更可取在C#中创建整个对话框。



如果您有键盘处理,空闲处理等混合UI,您可能需要做一些特殊处理来正确处理消息,激活......


So here is the setup. I have a large legacy codebase written in C++ and uses a lot of MFC. I created a new page/Class and need to use a C# form. using VS2010
* I was able to compile the single new class with the /clr flag.
* I was able to add a simple C# project to my solution and use it during a call.

Question is: How do I keep a handle to this C# object in my C++ Code. I realize my managed object reference needs to reside in the class definition, but I'm having issues getting it into the header. I could be misunderstanding some fundamental C++/CLI concepts.

I am trying to refactor as little legacy code as possible. This is why I used the option to set the single file/class to compile with /clr. I know that headers dont actually compile, and this is why there are no compilation options. This makes me unable to add the System references

Please see examples below for reference.

//Setup.h
#include "stdafx.h"
/* Doesn't Like these
using namespace System;
using namespace TestCSharpForm;
using namespace System::Windows::Forms;
*/
class SetupPage: public Page
{
public:
	void activate();
	void deActivate();
	
	SetupPage(Page* pParent = NULL);   
	virtual ~SetupPage();
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    

private:
//    TestCSharpForm::myForm^ myCSharpForm;
};
//END Setup.h


//Setup.cpp
using namespace System;
using namespace System::Windows::Forms;
using namespace TestCSharpForm;

SetupPage::SetupPage(GLTreePage *pParent): Page(UITreeWizard_InspectionSetup::IDD, pParent)
{
   //I have no member definition of TestCSharpForm to create
}


SetupPage::~SetupPage()
{
	clear();
}

//This works, and I can access the object locally within activate()
void SetupPage::activate()
{
    TestCSharpForm::myForm^ myCSharpForm = gcnew TestCSharpForm::myForm();
}



Thank you to anyone in advance for a solution, or a point in the correct direction. If I can provide any kind of clarification please let me know.

解决方案

Try this:

Quick and dirty. If your form can live as a singleton (only once instance at any time), declare it as static in Setup.cpp. It's not pretty but should work. However, I suggest keeping managed and unmanaged code separate.

Better: you already have an MFC project for you EXE and you've added a C# project for this new UI addition. Create a third project for your C++/CLI code. This will be your shim between the .NET and native code. You don't need an Active-X control (you can but it is more work). You'll end up with two assemblies and an EXE.

The C++/CLI assembly can export what is needed so that your MFC app can pass parameters and get back results. It is also possible to have native callback functions in the CLI wrapper that respond to delegates fired in your C# assembly.

You must constrain the C++/CLI to only include types valid in native C++. That means converting C# strings to MFC CStrings or STL std::strings.

As a rule, keep the amount of code in the CLI wrapper as small as possible. Do .NET work in the C# assembly and native work in the MFC app.

Don't forget to turn on "Mixed" debugging so you can step into / out of managed vs. unmanaged code in the debugger.

Good luck.


Please see my comment to the question.

First of all, #include "stdafx.h" is not like "using", not even close. This is just includes files, which is not needed in CLI in general, is just the C++-specific thing.

"Using" is also nothing special. This exactly like with unmanaged C++ "using". It does nothing, only introduces shortened type names. For example, you can use System::Windows::Forms::Form without any "using", or you can use using System::Windows::Forms, which would allow you to use Form without the full type name mentioned above…

I don't know what else could be unclear.

—SA


Although your question is not clear, the following might be useful if you need to keep an handle to a managed type Inside your native class.

How to: Declare Handles in Native Types[^]

If only some files are commpiled as managed, then usually you will either use 2 distinct pre-compiled header files or uses them only for native code file (those compiled without /clr option).

Even though I have done mixed mode programming, all the interface was managed in my case. If forms are used like a dialog, then it should not be hard to use them from your application but you might want to implement IWin32Window interface for ownership purpose...

Otherwise, if the UI is intended to be used Inside an MFC dialog, then I think that it should be user control on managed side (best to use C# for that) and they probably should be exported as Active/X controls. I have no experience into that but using Google, you should be able to do that. Here are some ot the top results for the search uses c# user control as activex:

http://www.codeguru.com/csharp/.net/net_general/comcom/article.php/c16257/Create-an-ActiveX-using-a-Csharp-Usercontrol.htm[^]

http://www.telerik.com/support/kb/winforms/details/wrapping-a-net-user-control-as-an-activex[^]

http://stackoverflow.com/questions/7409433/expose-a-winforms-usercontrol-as-an-activex-control[^]

If the page class you are creating is to be used Inside a stand-alone dialog that is not used by any MFC page, then in that case, I think it would preferable to make the whole dialog in C#.

You might have to do some special handling to properly handle messages if you have a mixed UI for things like keyboard processing, idle processing, activation...


这篇关于如何在C ++ / CLI类中保留对托管对象的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆