Search code examples
c#c++pinvoke

How can I change my C++ code to use as a DLL in C#?


I am learning how to call methods in C++ from C#. I have done some research and it seems Pinvoke is a nice way.

How can I translate this simple C++ code to the way how it should be in order to be called in C#, and how can I write the methods to be called in C#?

I have a header file:

MathFuncsLib.h

namespace MathFuncs
{
    class MyMathFuncs
    {
         public:            
       double Add(double a, double b);
       MyMathFuncs getClass();
    };
}

MathFuncsLib.cpp

#include "MathFuncsLib.h"
namespace MathFuncs
{
   MyMathFuncs MyMathFuncs::getClass() {
       return *(new MyMathFuncs());
   }

   double MyMathFuncs::Add(double a, double b) {
       return a + b;
   }
}

In C#,

I would like to have:

main()
{
    MyMathFuncs abd = MyMathFuncs::getClass();
    abd.Add(1.2, 2.3);
}

I have no clue how it should be achieved, so I think it is better to ask about it.


Solution

  • P/Invoke is more suited when you have a lot of static functions. You could instead use C++/CLI, which is more appropriate when you have a set of C++ classes, or a structured domain model hierarchy of classes. This is how you could do it with your sample:

    The .H:

    namespace MathFuncs {
    
        public ref class MyMathFuncs
        {
            public:            
                double Add(double a, double b);
        };
    }
    

    The .CPP:

    namespace MathFuncs
    {
       double MyMathFuncs::Add(double a, double b) {
           return a + b;
       }
    }
    

    The .CS:

    static class Program
    {
        static void Main()
        {
            MyMathFuncs abd = new MyMathFuncs();
            abd.Add(1.2, 2.3);
        }
    }
    

    As you see, you don't need the getClass function as with C++/CLI, your MathFuncs class becomes a full-blown .NET class.

    EDIT: if you want the actual computation (a+b in the sample) to happen in unmanaged code, you could do it like this; for example:

    The .H:

    namespace MathFuncs {
    
        public ref class MyMathFuncs
        {
            public:            
                double Add(double a, double b);
        };
    
        class MyMathFuncsImpl
        {
            public:            
                double Add(double a, double b);
        };
    }
    

    The .CPP:

    namespace MathFuncs
    {
        double MyMathFuncs::Add(double a, double b) {
            MyMathFuncsImpl *p = new MyMathFuncsImpl();
            double sum = p->Add(a, b);
            delete p;
            return sum;
        }
    
    #pragma managed(push, off)
        double MyMathFuncsImpl::Add(double a, double b) {
            return a + b;
        }
    #pragma managed(pop)
    }
    

    In this case, MyMathFuncsImpl::Add is generated as native code, not as IL (calling from C# is the same). See here: managed, unmanaged for more on how to mix managed and unmanaged code.