0
 int Set(CANMsg &CANObj)

我必须从 c# 调用上面的方法。直到现在我已经定义了一个包装器:

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

CANMsg CANObj --- 这个参数可以吗?或者我应该使用 CANMsg *CANObj 吗?

在这里我实现了包装器:

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

我正在创建这个包装器,因为这是函数的重载版本,我必须以某种方式有所作为。

这是 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;  

};

现在,在 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;
   }

导入是这样的:

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

我对那个 CANMsg 对象有点困惑,我是在将它声明为 IntPtr,marshal 还可以,还是类型?如果我让它这样,使用 IntPtr,我应该在那里执行什么样的实例化?如果我发送一个 CANMsg 对象,我会收到关于一些无效参数的错误。

如果您需要有关此的更多详细信息,请告诉我。

4

2 回答 2

1

您不能像这样将 C# 对象传递给本机 C++。Marshal.StructureToPtr 是你需要的,细节和例子在这里

于 2013-11-07T15:06:08.827 回答
1

当我看到你的 C++ 类定义时,我问自己“构造函数和析构函数发生了什么?” 和“做什么AddRef()Release()做什么?” 这些都是重要的问题,因为您不能简单地将 C# 对象中的数据投影到该 IntPtr 上并希望获得最好的结果。相反,您应该考虑制作一个为您工作的辅助 dll。您可能需要这样的方法:

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

我的 C++/CLI 生锈了,所以期待一些问题。如果这看起来像手动编组,那是因为鉴于您已经公开的类,您似乎需要它。

现在老实说,你可能不想要这个。实际上,您需要一个 C++/CLI 类,该类构造一个 CANMsg 并将其保留为私有成员,然后将 .NET 属性映射到较低级别的对象。这种类型的类必须是一次性的,!ClassName()析构函数将负责删除底层对象。

于 2013-11-07T15:32:15.677 回答