Click here to Skip to main content
15,882,209 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Good morning,
I am working on a project which combine C++ dll and C#. I have to make a kind of bridge between both. Now, I have to call C# functions inside C++ dll. for doing that, I made a C/ClI wrapper.
My project is divided in several parts :

- My C# code :
The file Class1.cs
C#
namespace ManagedClasses
{
  public class MessageShower
  {
    private string _message = "";

    public MessageShower()
      : this("TEST WRAPPER")
    {
    }

    public MessageShower(string message)
    {
      _message = message;
    }

    public void CreateArea(Area areaTest, Point pt1 , Point pt2, string message)
    {
      message = "Creation of area";
      Console.WriteLine(message);

      pt1 = new Point(2, 3);
      pt2 = new Point(4, 8);

      areaTest = new Area(pt1, pt2);
      Console.WriteLine("Area created");
      Console.WriteLine("Details of area :");
      Console.WriteLine(" -> BottomRight pt1({0},{1})", pt1.GetX(), pt1.GetY() );
      Console.WriteLine(" -> BottomRight pt2({0},{1})", pt2.GetX(), pt2.GetY() );

    }
    public int AddXPoints(Point a, Point b)
    {
      return (a.GetX() + b.GetX());
    }
    public void Show()
    {
      Console.WriteLine("Message Test : {0}", _message);
    }

    public int Add(int first, int second)
    {
      return first + second;
    }
  }
}


The file Class2.cs
C#
namespace WrapperTest
{
  public class Area 
  {
    public Area(Point pt1, Point Pt2)
    {
      BottomRight.SetX(pt1.GetX());
      BottomRight.SetY(pt1.GetY());

      TopLeft.SetX(Pt2.GetX());
      TopLeft.SetY(Pt2.GetY());
    }

    private Point BottomRight;
    private Point TopLeft;
  }

  public class Point
  {
    public Point() : this(0, 0) { }

    public Point(int a , int b)
    {
      x = a;
      y = b;
    }

    public void SetX(int a) { x = a; }
    public void SetY(int b) { y = b; }
    public int GetX() { return x; }
    public int GetY() { return y; }

    public void DisplayPoint()
    {
      Console.Write("Point : x({0}) , y({1})", x, y);
    }
    private int x;
    private int y;
  }
}


- My C\CLi wrapper use 3 C++ files :
The first one CLIWrapper.h :
C++
using namespace ManagedClasses;
using namespace System::Runtime::InteropServices;
using namespace abstractWrapper;


namespace CliWrapper
{
  public ref class Cli
  {
    Cli(void)
    {
      managedObject = gcnew MessageShower();
    }

    ~Cli()
    {
      delete CliInstance;
    }

  public :
    MessageShower^ managedObject;
    static Cli^ CliInstance = gcnew Cli();
  };
}

The .cpp files associated to the header : CLIWrapper.cpp
C++
#include "CLIWrapper.h"
#include "NativeInterface.h"


namespace CliWrapper
{
#ifdef __cplusplus
extern "C"
{
#endif
    __declspec(dllexport) void DisplayTest()
    {
      Cli::CliInstance->managedObject->Show();
    }

    __declspec(dllexport) int AddTest(int first, int second)
    {
      System::Int32 paramFirst = first;
      System::Int32 paramSecond = second;
      System::Int32 returnVal = Cli::CliInstance->managedObject->Add(paramFirst, paramSecond);
      return returnVal;
    }
#ifdef __cplusplus
}
#endif
}


The file concerning the declaration of the function which be called in C++ dll : NativeInterface.h :
C++
#ifdef __cplusplus
extern "C"
{
#endif
  __declspec(dllexport) void DisplayTest();
  __declspec(dllexport) int AddTest(int first, int second);
#ifdef __cplusplus
}
#endif


I test it in a main program in C++ and I can call the function DisplayTest and AddTest.

Now I would like to do the same with the function CreateArea (in Class1.cs in C#). For doing the same thing, I have to transform C# object like Area , Point to unmanaged types which can be understood by C++ and I don't know how to do it.
So I would like to know if someone have an idea to do that.

Thanks in advance.
Posted
Comments
Philippe Mori 2-Sep-13 12:10pm    
Do you have any reason to call C# code from C code? Managed/unmanaged boudary crossing will cost some CPU time.

What is the prupose of using C#. I ask those questions as I have done an application having C++/CLI and C# projects and I find that it make thje application harder to debug and maintain with marginal benefit so you have to be sure that what you are doing is the most appropriate solution to your problem.

C++/CLI is able to used your managed types so why would you want to convert them.

And if you have to convert them to a format used by another library (or so that the code can be used from C code), then it can be done in wrapper code so where is the problem?

By the way, you should also cleanup your code with useless or wrong code.

CLIWrapper.cpp can only be compiled in C++/CLI so it is pointless to have #ifdef __cplusplus / #endif pair in that code.

C does not understand C++ namespace so I think that extern C function should not be declared inside a namespace.

Cli::~Cli should not destroy a static instance (of it own type). This would result in an infinite loop. In fact, you probably want to delete managedObject instead.

What is the purpose of all System::Int32 in AddTest function as int ans System::Int32 are essentially the same thing. It only make the code longer than necessary.
 
Share this answer
 
v3
Phillipe's answer is correct. However, I am going to assume you have an unmanaged application that you want to call C# code from and don't want to compile it all together.

If your example above is going to be placed into code and is not just test code to play with, I would first recommend changing your Point class to use the Point structure in System.Drawing and the Area class to use the Rectangle structure in System.Drawing.

In any case, you will need to do marshaling. If you make the changes I mentioned above, then the default marshaling should be ok.

Here is a link on default marshaling. It goes from C# calling unmanaged code, but it should be the same in the opposite direction.

http://msdn.microsoft.com/en-us/library/0t2cwe11.aspx[^]
 
Share this answer
 
Concerning the code, it is a test code in order to try and test the possibilities that I have to communicate between C# and C++. Actually, I need to know if it is possible to use a managed object as a parameter in a C++ function and to try it. What do you mean by " And if you have to convert them to a format used by another library (or so that the code can be used from C code), then it can be done in wrapper code " ?

Concerning the MSDN link, I already did marshalling in the opposite direction and it works fine.

Also, thank for your adivces in order to clean the code, I will do it. And by the way, how can I delete managedObject
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900