I am trying to use a C# DLL which has multiple references to .NET classes and C# Classes in Embarcadero C++ Builder.
Things like the Point class and String class as well as Delegates.
I am wondering if the >NET references or C# ones will mess me up somehow. I am just about to getting it hooked up, but I am wondering if some of the problems I am having could be caused by C++ not wanting to play nice.
I gave a similar answer to your problem in this question.
You basically want a C++/CLI interface to your C# code.
If you want to pass a C# delegate to C++ code, you can translate it using Marshal::GetFunctionPointerForDelegate()
(MSDN). That gives you a IntPtr
that you can call ToPointer()
on to pass in as a function pointer.
You will need to use C++/CLI to use any .NET content in C++. You might also be able to set up your own AppDomain, but those are the only two choices, as C++ has no native ability to interact with .NET, at all.
Or you can use the mono CLR embedder
Managed code can invoke unmanaged code in two ways, [using P/Invoke or] using the low-level Mono embedding API.
This works a lot like the oldfashioned embedding of a Perl, Python or Ruby 'interpreter' (actually, virtual machines) in your C/C++ executable. I don't think there is actually such a thing as a Swig(++) wrapper generator for this (yet), but here is a snippet of what a call into CIL code looks like:
class MyClass {
static void Foo (int value) {
...
}
int Bar (string name) {
...
}
}
assuming you got the corresponding MonoMethod* in foo_method and bar_method and this_arg is a MonoObject* of type MyClass, you simply execute:
/* we execute methods that take one argument */
void *args [1];
int val = 10;
/* Note we put the address of the value type in the args array */
args [0] = &val;
/* execute Foo (10);
* it's a static method, so use NULL as the second argument.
*/
mono_runtime_invoke (foo_method, NULL, args, NULL);
/* a string is a reference, so we put it directly in the args array */
args [0] = mono_string_new (domain, "Hello");
/* execute my_class_instance.Bar ("Hello");
* See the Creating Objects section to learn how to get this_arg.
*/
MonoObject *result = mono_runtime_invoke (bar_method, this_arg, args, NULL);
/* we always get a MonoObject* from mono_runtime_invoke (), so to get
* the integer value we need to unbox (which returns a pointer to
* the value stored in the object) and dereference.
*/
int int_result = *(int*)mono_object_unbox (result);
For extra entertainment value: if you AOT-compile all of your CIL code, you'll be able to statically link your assembly into your native binary (effectively doing what Managed C++ (c++-cli) calls mixed mode assemblies). Look at
mono --aot=static myassembly.dll
and
mkbundle