Reputation: 1780
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
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
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
Reputation: 116744
Try:
ManagedWrapper::ManagedDialogProvider::ShowDialog();
Upvotes: 0