简体   繁体   English

使用引用类型作为参数从c#调用c ++函数

[英]calling c++ function from c# with a reference type as parameter

 int Set(CANMsg &CANObj)

I have to call the method above, from c#. 我必须从c#调用上面的方法。 Untill now i have defined a wrapper : 直到现在我已经定义了一个包装器:

 extern "C" __declspec(dllexport) int SetWrapper(CANMsg CANObj);

CANMsg CANObj --- is this parameter ok or should i use CANMsg *CANObj ? CANMsg CANObj ---这个参数是ok还是我应该使用CANMsg * CANObj?

and here i implement the wrapper: 在这里我实现了包装器:

 extern "C" __declspec(dllexport) int SetWrapper(CANMsg CANObj)
 { 
      return Set(CANObj);
 }

I am creating this wrapper because this is an overloaded version of the function and i had to make a difference somehow. 我正在创建这个包装器,因为这是函数的重载版本,我不得不以某种方式有所作为。

Here is the CANMsg class: 这是CANMsg类:

 class CANMsg
 {
 public:
 CANMsg();
 ~CANMsg();

 void AddRef() const;
 void Release() const;
 unsigned int MsgId;
 unsigned int DLC;
 unsigned int Handle;
 unsigned int Interval;
 unsigned int TimeStamp;
 unsigned char Data0;
 unsigned char Data1;
 unsigned char Data2;
 unsigned char Data3;
 unsigned char Data4;
 unsigned char Data5;
 unsigned char Data6;
 unsigned char Data7;

  protected:

mutable int refCount;  

};

Now, in C# i have the following : 现在,在C#中我有以下内容:

      [StructLayout(LayoutKind.Sequential)]
      public class CANmsg
   {
      public  int MsgId;
      public int DLC;
      public int Handle;
      public int Interval;
      public int TimeStamp;
      public char Data0;
      public char Data1;
      public char Data2;
      public char Data3;
      public char Data4;
      public char Data5;
      public char Data6;
      public char Data7;
   }

and the import is like this : 和导入是这样的:

     [DllImport("engine.dll", CallingConvention = CallingConvention.Cdecl)]
  [return: MarshalAs(UnmanagedType.I4)]
  public static extern int SetWrapper(IntPtr canMSGObject);

I am a bit confused about that CANMsg object, am I declaring it ok as an IntPtr, is the marshal ok, or the types ? 我对CANMsg对象有点困惑,我是否认为它可以作为IntPtr,是元帅,还是类型? If i let it like so, with the IntPtr, what kind of instantiation should i perform there? 如果我喜欢它,使用IntPtr,我应该在那里执行什么样的实例化? If i send a CANMsg object, i get an error regarding some invalid arguments. 如果我发送一个CANMsg对象,我得到一些关于一些无效参数的错误。

Let me know if you need some more details about this. 如果您需要更多详细信息,请与我们联系。

You can not pass a C# object to native C++ like this. 您无法像这样将C#对象传递给本机C ++。 Marshal.StructureToPtr is what you need, the details and examples are here Marshal.StructureToPtr就是您所需要的,详细信息和示例都在这里

When I see your C++ class definition, I ask myself "what happens in the constructor and the destructor?" 当我看到你的C ++类定义时,我会问自己“构造函数和析构函数中会发生什么?” and "what do AddRef() and Release() do?" 和“ AddRef()Release()做什么?” These are important questions because you can't simply project data from a C# object onto that IntPtr and hope for the best. 这些都是重要的问题,因为您不能简单地将数据从C#对象投影到该IntPtr上,并希望获得最佳效果。 Instead, you should think about making a helper dll that does this work for you. 相反,你应该考虑制作一个帮助你的助手dll。 You might need methods something like this: 你可能需要这样的方法:

public ref class MyLibraryHelper {

public:
    IntPtr MakeCANMsg() { return gcnew IntPtr(new CANMsg()); }
    void DestroyCANMsg(IntPtr msgPtr) {
       CANMsg *msg = reinterpret_cast<CANMsg *>(msgPtr.ToPointer());
       if (msg) delete msg;
    }
    void ProjectTo(CSharpCANMsg ^csh, IntPtr msgPtr)
    {
       CANMsg *msg = reinterpret_cast<CANMsg *>(msgPtr.ToPointer());
       if (!msg) return;
       msg->MsgId = csh->get_MsgId();
       // etc
    }
    void ProjectFrom(IntPtr msgPtr, CSharpCANMsg ^csh)
    {
       CANMsg *msg = reinterpret_cast<CANMsg *>(msgPtr.ToPointer());
       if (!msg) return;
       csh->set_MsgId(msg->MsgId);
       // etc
    }
}

My C++/CLI is rusty, so expect some issues. 我的C ++ / CLI很生疏,所以期待一些问题。 If this looks like hand-marshalling, well, it is because given the class that you've exposed, it seems like you need it. 如果这看起来像是手工编组,那么,这是因为根据你所暴露的课程,你似乎需要它。

Now honestly, you probably don't want this. 老实说,你可能不想要这个。 Really, you want a C++/CLI class that constructs a CANMsg and keeps it as a private member and then maps .NET properties onto the lower level object. 实际上,您需要一个C ++ / CLI类来构造一个CANMsg并将其保存为私有成员,然后将.NET属性映射到较低级别的对象上。 This type of class will have to be disposable and the !ClassName() destructor will be responsible for deleting the underlying object. 这种类必须是一次性的,而!ClassName()析构函数将负责删除底层对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM