Using a Very C# DLL in C++

2019-09-11 02:58发布

问题:

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.

回答1:

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.



回答2:

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.



回答3:

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