views:

1165

answers:

4

I've done the other way around (Calling pure C++ code from .Net) with C++/CLI and it worked (for the most part).

How is the native->c++/cli direction done?

I really don't want to use COM interop...

A: 

Calling .NET code from C++/CLI is very straightforward. Its very similar to regular C++. Make sure your project is setup as a C++/CLI project, add a reference to your .NET assembly by going to the project properties under "Common Properties", then use your .NET objects with some code like this:

using namespace System;
using namespace System::Collections::Generic;
using namespace MyNamespace;

void MyFunctionCall()
{
  MyObject ^obj = gcnew MyObject();
  obj->MyMethod();

  // ...
}
heavyd
That only works in a .NET (/clr) application. I believe the OP is asking how to do it when the application is purely a native C++ app.
Harper Shelby
+4  A: 

You can always host the CLR in your native app.

Harper Shelby
A: 

the book C++/CLI in Action has a chapter named Mixing Managed and Native Code and inside the chapter, under Working With Interop Mechanisms heading it talks about both accessing a managed library from native code and accessing a native library from managed code. It did help me get the concepts when i read it once upon a time.

davsan
+6  A: 

If you have an existing native C++ app and want to avoid "poluting" it with too much CLR stuff, you can switch on the /clr flag for just one specific file and use a standard C++ header to provide an interface to it. I've done this in an old bit of code. In the header I have:

void SaveIconAsPng(void *hIcon, const wchar_t *pstrFileName);

So the rest of the program has a simple API to which it can pass an HICON and a destination filepath.

Then I have a separate source file which is the only one that has /clr switched on:

using namespace System;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace System::Drawing::Drawing2D;

#include <vcclr.h> 
#include <wchar.h>

void SaveIconAsPng(void *hIcon, const wchar_t *pstrFileName)
{
 try
 {
  Bitmap bitmap(16, 16, PixelFormat::Format32bppArgb);

  Graphics ^graphics = Graphics::FromImage(%bitmap);
  graphics->SmoothingMode = SmoothingMode::None;

  Icon ^icon = Icon::FromHandle(IntPtr(hIcon));
  graphics->DrawIcon(icon, Rectangle(0, 0, 15, 15));
  graphics->Flush();

  bitmap.Save(gcnew String(pstrFileName), ImageFormat::Png);
 }
 catch (Exception ^x)
 {
  pin_ptr<const wchar_t> unmngStr = PtrToStringChars(x->Message);
  throw widestring_error(unmngStr); // custom exception type based on std::exception
 }
}

That way I can convert HICONs into .png files from my hairy old C++ program, but I've isolate the use of the .NET framework from the rest of the code - so if I need to be portable later, I can easily swap in a different implementation.

You could take this a stage further and put the CLR-dependent code in a separate DLL, although there would be little added value in that unless you wanted to be able to patch it separately.

Daniel Earwicker
+1. Sounds like an elegant solution.
OregonGhost
It's the one recommended by Stroustrup! http://www.research.att.com/~bs/bs_faq.html#CppCLI - "design applications so that access to system-specific facilities are through well-defined interfaces specified in ISO C++"
Daniel Earwicker
Nice - I wasn't aware you could limit the CLR usage like that.
Harper Shelby
But how do you then call this code from a native process (e.g. one without a managed heap)?IIUC, the whole process has to be managed, but you may compile some of the translation units as pure native. I guess that's handy, but doesn't quite solve the problem of invoking managed code from unmanaged processes.
Assaf Lavie
@Assaf - Clearly managed code requires a managed heap (or more properly an instance of the runtime, which includes a heap), and so if any process is going to run managed code directly, it would need to instantiate the runtime. If you try to get around that, you're just going to be going around in circles! C++/CLI makes it super convenient anyway. If you want to do it the hard way, see http://msdn.microsoft.com/en-us/magazine/cc163567.aspx for the details - you can control very many aspects of how it works, and you don't have to change the project settings. But it won't look as pretty.
Daniel Earwicker