如何将结构作为参数从 c++/cli 传递到 c++
How to pass struct as parameter from c++/cli to c++
我的代码有3个部分:c#,c ++/cli,c ++。
在 C# 中,我有一个结构体。结构被定义为传递参数。
//c#
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack=1)]
public struct NDeviceDest
{
public uint IP;
public uint pos;
}
然后在 c++/cli 中,我有一个使用 NDeviceDest 的函数
//c++/CLI
byte NDockMaster::Init(NDeviceDest pos, uint param)
{
m_pDockMaster->Init(static_cast<DeviceDest*>pos, param);
}
*m_pDockMaster* 是指向本机类型的指针。
Init 的成员函数在 c++ 中定义为 ()
//c++
struct DeviceDest
{
UINT32 IP;
unsigned int pos;
};
class DockMaster
{
public:
byte Init(DeviceDest* dest, UINT32 param)
{
return 0;
}
}
DeviceDest 被定义为与 NDeviceDest 完全相同,以传递参数。
问题:
在我的 c++/cli 代码中,我使用 *static_cast* 进行类型更改。 但是我遇到了编译错误:
error C2440: 'static_cast' : cannot convert from 'NDeviceDest' to 'DeviceDest *'
我是 c++/cli 的新手,但我认为必须有一种方法可以让编译器知道 NDeviceDest 是 DeviceDest,并让我编码编译并将值从 c# 传递到 cli 再到 c++,但我搜索了很多,没有找到确切的答案。
我确实找到了一些代码,但它使用的是指针而不是结构,我也尝试使用指针,但我有同样的错误。
谢谢
不,编译器不会让你这样做。 即使是C型施法或reinterpret_cast<>()也不起作用,这是你拥有的最大武器。
这是有充分理由的,托管结构与非托管结构非常不兼容。 第一个问题是布局,结构成员的确切顺序和偏移量。 从技术上讲,这是一个较小的问题,CLR 已经尝试使它们保持不变。 通常是匹配的,并非总是如此。 您将在这篇文章中找到更多详细信息。
更大的问题是存储,托管结构倾向于在可以随机更改的地址上分配。 垃圾回收器的副作用是,它的职责之一是不仅释放未使用的内存,而且还压缩堆。 与本机代码使用您传递的指针的方式非常不兼容,它会随机取消对错误地址的结构的引用。 要么是因为它释放了封闭对象,要么是因为它移动了它。 调试非常困难,因为它很少发生,并且完全不确定,因为它依赖于分配的其他托管线程。
所以它只是简单地禁止它。 必须封送结构,将其复制到非托管内存中,然后重新排列以匹配本机布局。 通用帮助程序函数是 Marshal::StructureToPtr()。 但是对于这么小的结构来说完全没有必要,自己复制字段要更快、更简单:
Byte Init(NDeviceDest pos, unsigned param) {
DeviceDest unmanagedPos = { pos.IP, pos.pos };
m_pDockMaster->Init(&unmanagedPos, param);
//...
}
满足要求,它保证了正确的布局。 并且分配在稳定的内存中,GC 不会弄乱堆栈位置,并且内存在方法主体执行期间是稳定的。 如果需要说,可能不需要,请确保"DockMaster"不存储传递的指针。
您看到的错误是不允许static_cast从struct
转换为struct *
。因此,c++/cli 接口中的正确调用是
m_pDockMaster->Init(static_cast<DeviceDest*>(&pos), param);
如果这是一个类查找问题,并且如果您使用的是指针并且您确定封送处理是正确的,请尝试使用 reinterpret_cast。
m_pDockMaster->Init(reinterpret_cast<DeviceDest*>pos, param);
但乍一看,您正在尝试将非指针类型转换为指针类型。您应该使用 NDeviceDest* pos 作为输入参数,或者
m_pDockMaster->Init(static_cast<DevideDest*>&pos,param) .
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL
- C++/CLI System.AccessViolation在托管类中调用非托管函数时出现异常
- 是否可以在Linux上使用.Net Core 3.1创建C++/CLI代码的C#DLL
- C++ DLL(不是 CLI)是否可以调用 .NET Core 3.0 委托?
- VS2010 C++ 调试托管 (C++/CLI) DLL
- 如何将 C++/CLI 库链接到C++应用程序
- C++/CLI targetting .NET Core 3.1
- 模板函数签名在 C++/CLI 中解包
- C++/CLI 混合托管/本机 DLL 不起作用
- C++/CLI 和 C#/VB 与不安全和外部有什么区别?
- 是否有可能构建面向Linux和Windows的.Net Core C++ / CLI应用程序?
- DirectX 12 和 C++ CLI :无法使用IID_PPV_ARGS
- 如何为要在 C# 中使用的静态库创建 C++ 或 C++/CLI 包装器
- 将 C# 对象(包含静态对象成员)作为参数传递给 C++/CLI 程序
- C++/CLI -- 访问结构成员
- 如何将字符串从 C++/CLI 方法返回到调用它的非托管C++
- 如何将CLI类的函数指针作为参数传递给C++方法
- 用于LabView中使用的本机c++的c++/cli dll包装器
- C#WPF和C++/CLI以及C++在C++/CLI中添加外部库错误
- 在.NET Core 3.1中运行托管C++/CLI程序集时,映像格式错误