C ++ / CLI:如果不使用#include,则无法看到引用的程序集

时间:2011-04-05 14:26:38

标签: .net visual-c++ c++-cli interop

我们有两个C ++ / CLI项目,一个纯CLR项目和一个混合模式项目,它存在以提供我们对纯CLR项目的非托管代码库访问。我们无法让混合模式项目看到纯CLR项目中定义的符号。

具体来说,我们有一个表单,称之为MainForm,在纯粹管理的项目中定义。这是典型的C ++ / CLI Windows窗体:

MainForm.h:

public ref class MainForm : public System::Windows::Forms::Form
{
public:
    MainForm(void)
    {
        InitializeComponent();
        //
        //TODO: Add the constructor code here

    }
    ...
};

我们的混合模式“包装器”项目尝试使用它,如下所示:

ManagedDialogProvider.h:

namespace ManagedWrapper
{
    public ref class ManagedDialogProvider
    {
        static void ShowDialog()
        {
             OurManagedComponents::MainForm^ form = gcnew OurManagedComponents::MainForm();
        }
    };
}

(然后我们在混合模式项目CManagedDialogProvider中有一个C ++ / MFC类,它调用ManagedDialogProvider以便我们的非托管代码可以使用它。但是,那里没有发生错误。)

当我尝试构建混合模式项目时,它告诉我MainForm不是OurManagedComponents的成员。 (ManagedWrapper :: ManagedDialogProvider :: ShowDialog()中的错误。)

注意:

  • 混合模式项目引用了托管项目。
  • 我尝试在托管包装类的顶部使用#include而不是引用,并且在编译时,由于找不到资源,我无法加载表单。我退出了这个解决方案,因为如果我理解正确,这是不被接受的做法; .NET项目应该仅通过程序集引用相互引用。
  • 我已经验证托管类是可访问的(公共)。
  • 我检查了对象浏览器,以确保OurManagedComponents可见并包含MainForm。

有什么想法吗?相同的混合模式项目在包装C#托管组件时没有问题,但是当我尝试对此C ++ / CLI托管组件使用相同的方法时,会出现这些问题。

3 个答案:

答案 0 :(得分:2)

事实证明,OurManagedComponents :: MainForm没有实现文件(.cpp);它只有一个.h文件。很自然,MainForm从未实际构建或链接到项目中。 (有趣的是,对象浏览器仍然显示OurManagedComponents :: MainForm并且项目仍然构建得很好;它必须看到声明的类型,无论它们是否已实现)。我能说什么,我一直在使用C#太长了: - )

一旦我创建了一个MainForm.cpp(空的但是包含“MainForm.h”)并重建,一切都运转了。

答案 1 :(得分:0)

尝试:

ManagedWrapper::ManagedDialogProvider::ShowDialog();

答案 2 :(得分:0)

  

然后我们有一个非托管类   调用的那个项目   ManagedDialogProvider让我们的   非托管代码可以使用它。

如果没有正确的回调,非托管(本机)代码无法访问托管代码 想想下面的代码。

// CMainDialogProvider.h

typedef void (*ShowDialogNativeCB)() ;

class CMainDialogProvider
{
//..
public:
  ShowDialogNativeCB nativeCB;
//..

}

// ManagedDialogProvider.h
#include "CMainDialogProvider.h"

public delegate void ShowDialogClrCB ();

namespace ManagedWrapper
{
   // ....
   //somehow you have to provide the ShowDialog() function as a callback;
   ShowDialogClrCB ^ clrCB = gcnew ShowDialogClrCB(&ManagedDialogProvider::ShowDialog());
   GCHandle clrCBhandle = GCHandle::Alloc(clrCB);
   // to prevent the garbage collection of delegate.
   // but this must be freed later. 
   IntPtr ip = Marshal::GetFunctionPointerForDelegate(clrCB);
   // Lets say Instance is an instance of CMainDialogProvider.
   Instance->nativeCB = static_cast<ShowDialogNativeCB>(ip.ToPointer());
   //...
}

#include "stdafx.h"
#include "CManagedDialogProvider.h" // C++ class
#include "ManagedDialogProvider.h"  // .NET ref class

IMPLEMENT_DYNAMIC(CManagedDialogProvider, CObject)

void CManagedDialogProvider::ShowDialog()
{
   if(nativeCB != NULL)
     nativeCB();
}