System.Cats.Lol
System.Cats.Lol

Reputation: 1780

C++/CLI: Cannot see referenced assemblies without using #include

We have two C++/CLI projects, a pure CLR project and a mixed-mode project that exists to provide our unmanaged codebase access to the pure CLR project. We are having trouble getting the mixed-mode project to see symbols defined in the pure CLR project.

Specifically we have a form, call it MainForm, defined in the purely-managed project. It's a typical C++/CLI Windows Form:

MainForm.h:

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

    }
    ...
};

Our mixed-mode "wrapper" project tries to use it, like so:

ManagedDialogProvider.h:

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

(We then have a C++/MFC class in the mixed-mode project, CManagedDialogProvider, that calls ManagedDialogProvider so that our unmanaged code can use it. The error isn't occurring there, however.)

When I try building the mixed-mode project, it tells me that MainForm is not a member of OurManagedComponents. (Error in ManagedWrapper::ManagedDialogProvider::ShowDialog().)

Notes:

Any ideas? The same mixed-mode project has no trouble wrapping C# managed components, but when I tried using that same approach for this C++/CLI managed component, these issues appeared.

Upvotes: 2

Views: 1376

Answers (3)

System.Cats.Lol
System.Cats.Lol

Reputation: 1780

It turned out that OurManagedComponents::MainForm had no implementation file (.cpp); it only had a .h file. So naturally, MainForm was never actually built or linked in to the project. (Interestingly, the object browser still showed OurManagedComponents::MainForm and the project still built just fine; it must see declared types regardless of whether they are implemented). What can I say, I've been using C# too long :-)

Once I created a MainForm.cpp (empty but for include "MainForm.h") and rebuilt, everything worked.

Upvotes: 2

ali_bahoo
ali_bahoo

Reputation: 4873

We then have an unmanaged class in that same project that calls ManagedDialogProvider so that our unmanaged code can use it.

Unmanaged (native) code can not reach to managed code without proper callbacks.
Think about the code below.

// 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();
}

Upvotes: 0

Daniel Earwicker
Daniel Earwicker

Reputation: 116744

Try:

ManagedWrapper::ManagedDialogProvider::ShowDialog();

Upvotes: 0

Related Questions