Thanks to help on this list I've come a long way in embedding mono into
my C++ application. During the transition of a very large
application (25+ yrs of C, Fortran, & C++) towards managed code, we
will be adding new code in .NET languages, but needing to access these
objects from C++ fairly intimately. Therefore I'm looking at writing
wrappers which expose CLR classes as C++ classes -- without resorting
to (XP)COM or CORBA. I figure most of these can be auto-generated. I believe it
will make sense to emit mono-embedding wrappers for Linux and Managed
C++ wrappers for Windows. If anyone else is interested (or has already
undertaken!) such an effort, let me know. However I&#39;m still looking at some marshalling issues.<br>

<br>

If I call .NET functions exclusively via the embedding reflection API,
e.g. mono_runtime_invoke, and carefully call g_free on returned
copies of things like strings, everything works fine, including managed exceptions. It seems
that&nbsp; by caching the reflected objects, e.g. MonoMethod*, performance
is good.<br>

<br>

However I am having problems with delegates invoked across the barrier.
They execute properly, but appear to leak memory, and I am not sure how
to catch exceptions they might throw. For the majority of our interop,
we can avoid attempting this scenario, but we&#39;d like to investigate it
so that we can provide managed callbacks for unmanaged code to call.<br>

<br>

In our C++, we define (using MSVC syntax for this prototype)<br>

<blockquote>// function: string-&gt;string<br>
typedef char* (__stdcall * action_string)(char*);<br><br>
// managed code will stash a delegate here for use by unmanaged code<br>
action_string _f_string;<br>
extern &quot;C&quot; _declspec(dllexport) void __stdcall
init_string(action_string f)<br>
{&nbsp; _f_string =f ; }<br>
  <br>
// the unmanged code actually calls this code, e.g. do_string(&quot;hello&quot;)<br>
extern &quot;C&quot; _declspec(dllexport) char* __stdcall do_string(char* s);<br>
  {&nbsp; return _f_string(s); }<br>
</blockquote>
then in C# we write<br>
<blockquote>// function: string-&gt;string, equivalent to action_string above<br>
public delegate string ActionString(string _);<br>
  <br>
// the managed code we&#39;ll be calling from unmanaged code<br>
public static string Echo(string s) { return s+s; }<br>
  <br>
// and the bootstrapper<br>
[DllImport(&quot;libhost&quot;)] public static extern void init_string(ActionString s);<br>
public static void Boot { init_string(Echo); }<br>
</blockquote>
and again in C++, we can actually call the managed code like so<br>
<blockquote>// find_method is just a shortcut using debug-helpers<br>
MonoMethod *bootMethod = find_method(&quot;Hello.World:Boot&quot;, image);<br>
&nbsp;mono_runtime_invoke(bootMethod, NULL, NULL, NULL);<br>
// now we have a function pointer we can call<br>
char *result = do_string(&quot;hello&quot;);<br>
g_free(result);<br>
</blockquote>
Everything works. However, there appears to be a memory leak. I am not
sure whether it is the input that is leaking (i.e. a copy of&nbsp;
char*&quot;hello&quot; turned into utf16&quot;hello&quot;), or if I am improperly freeing
the output (which I must assume is a copied string) or something else
in the internals. What is encouraging is that all the marshalling is
correct, just leaky. Also, if the managed code throws an exception, the
program prints an error message (&quot;uncaught exception&quot;) and hangs. I am
not sure what I would have expected on the C++ side, perhaps a C++
exception, perhaps silence.<br>
<br>
>From the fact that the function pointers work at all, I can tell a lot
of thought has already gone into this PInvoke stuff. What am I missing
on the garbage collection side? (And as soon as the strings work, I
need to worry about making sure that managed delegate doesn&#39;t move or
get garbage collected!)<br>
<br>
Thanks<br>
<br>
Sebastian