将托管对象作为参数传递给C / CLI Wrapper函数以导出到本机Win32 dll [英] Passing a managed Object as parameter in C /CLI Wrapper Function to be exported to native Win32 dll

查看:57
本文介绍了将托管对象作为参数传递给C / CLI Wrapper函数以导出到本机Win32 dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

早上好,

我正在开发一个结合C ++ dll和C#的项目。我必须在两者之间建立一种桥梁。现在,我必须在C ++ DLL中调用C#函数。为此,我制作了一个C / ClI包装器。

我的项目分为几个部分:



- 我的C#代码:

文件Class1.cs

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

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;
    }
  }
}





文件Class2.cs



The file Class2.cs

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;
  }
}





- 我的C\CLi包装使用3个C ++文件:

第一个CLIWrapper.h:



- My C\CLi wrapper use 3 C++ files :
The first one CLIWrapper.h :

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();
  };
}



与标题关联的.cpp文件:CLIWrapper.cpp


The .cpp files associated to the header : CLIWrapper.cpp

#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
}





关于在C ++ dll中调用的函数声明的文件:NativeInterface.h:



The file concerning the declaration of the function which be called in C++ dll : NativeInterface.h :

#ifdef __cplusplus
extern "C"
{
#endif
  __declspec(dllexport) void DisplayTest();
  __declspec(dllexport) int AddTest(int first, int second);
#ifdef __cplusplus
}
#endif





我用C ++在主程序中测试它,我可以调用DisplayTest和AddTest函数。



现在我想对CreateArea函数(在C#中的Class1.cs中)做同样的事情。为了做同样的事情,我必须将C#对象转换为Area,Point转换为非托管类型,这些类型可以被C ++理解,我不知道如何去做。

所以我想知道是否有人有这样的想法。



提前谢谢。



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.

推荐答案

C ++ / CLI能够使用您的托管类型,所以为什么要转换它们。



如果你需要将它们转换为另一个库使用的格式(或者可以从C代码中使用代码),然后可以用包装器代码完成,那么问题出在哪里?



顺便说一句,你还应该用无用或错误的代码清理你的代码。



CLIWrapper.cpp只能在C ++ / CLI中编译,所以它没有意义在该代码中有 #ifdef __cplusplus / #endif 对。



C不理解C ++命名空间,所以我认为extern C函数不应该在命名空间内声明。



Cli: :~Cli 不应该破坏静态实例(它自己的类型)。这将导致无限循环。实际上,您可能想要删除 managedObject



所有<$ c $的目的是什么c> System :: Int32 在 AddTest 函数中作为int和System :: Int32本质上是一回事。它只会使代码超出必要的时间。
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.


Phillipe的答案是正确的。但是,我假设您有一个非托管应用程序,您想要从中调用C#代码,并且不想一起编译它们。



如果您的示例上面将放入代码并且不仅仅是要使用的测试代码,我首先建议更改Point类以使用System.Drawing中的Point结构和Area类来使用System.Drawing中的Rectangle结构。 br />


无论如何,你需要做编组。如果你进行了我上面提到的更改,那么默认封送应该没问题。



这是默认编组的链接。它来自C#调用非托管代码,但它应该是相反的方向。



http://msdn.microsoft.com/en-us/library/0t2cwe11.aspx [ ^ ]
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[^]


关于代码,它是一个测试代码,按顺序尝试测试我必须在C#和C ++之间进行通信的可能性。实际上,我需要知道是否可以使用托管对象作为C ++函数中的参数并尝试它。你是什​​么意思如果你必须将它们转换为另一个库使用的格式(或者代码可以从C代码中使用),那么它可以用包装代码完成?



关于MSDN链接,我已经在相反的方向上进行了编组工作并且工作正常。



此外,感谢您的支持为了清理代码,我会这样做。顺便说一下,如何删除 managedObject
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


这篇关于将托管对象作为参数传递给C / CLI Wrapper函数以导出到本机Win32 dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆