如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
What happens if a string in a struct is longer or shorter than the p/Invoked signature used?
举个例子,我想使用C#中的DEV_BROADCAST_DEVICEINTERFACE_A。但是,我不确定如何声明结构,因为dbcc_name
的大小取决于dbcc_size
(正式声明为char dbcc_name[1]
(。
根据这个问题,我似乎需要添加
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)]
超过dbcc_name
.
但是为什么要使用SizeConst=255
?我们不知道大小。(从我看到的其他答案来看,似乎没有简单的方法来声明它,以便它知道正确的大小或逐个指定大小的方法。
那么如果我像链接答案中那样设置静态长度会发生什么。如果字符串更短或更长会发生什么?
测试表明,如果它更长,我会得到正确的字符串,如果更短 - 我会得到一个截断的字符串(例如,如果我将 SizeConst 设置为 2 并且真正的字符串是"abc",我会得到"ab"。但是我能确定这就是它的工作原理,还是取决于在这种特定情况下恰好没问题的东西?
你不能完全声明结构,你可以做的是这样的:
[StructLayout(LayoutKind.Sequential)]
private struct _DEV_BROADCAST_DEVICEINTERFACE_A
{
public int dbcc_size;
public uint dbcc_devicetype;
public uint dbcc_reserved;
public Guid dbcc_classguid;
public char dbcc_name; // just for offset; don't use!
}
并像这样使用它:
// get ptr to structure from somewhere (lParam from WM_DEVICECHANGE ...)
IntPtr ptr = ...
// read structure
var iface = Marshal.PtrToStructure<_DEV_BROADCAST_DEVICEINTERFACE_A>(ptr);
// get name pointer
var namePtr = ptr + Marshal.OffsetOf<_DEV_BROADCAST_DEVICEINTERFACE_A>(nameof(_DEV_BROADCAST_DEVICEINTERFACE_A.dbcc_name)).ToInt32();
// get name
var name = Marshal.PtrToStringAnsi(namePtr);
请注意,如果名称可以包含零,则应改为将Marshal.PtrToStringAnsi(namePtr, len)
与len = dbcc_size - offset of dbcc_name
一起使用
相关文章:
- 什么时候调用组成单元对象的析构函数
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 如果在 DLL 和调用应用程序中使用 GPGPU API,会发生什么情况
- 如果从在其他函数中调用的函数引发异常会发生什么情况
- 如果在调用 DLL 中的函数时没有传递足够的参数,会发生什么情况?
- 在声明纯虚函数的父类的实例上调用纯虚函数时会发生什么情况
- visual在什么情况下调用C++复制构造函数
- 从派生类调用基函数时会发生什么情况
- 一个函数调用另一个函数时使用的内存会发生什么情况
- 如果我在 C++ 中调用 new,但堆内存不足,会发生什么情况
- 在什么情况下afx_msg可以调用 void OnDestroy( ) 又名 CWnd:OnDestroy()
- 何时正确定义放置新放置,以及调用放置 new 时现有类型会发生什么情况
- 当按引用传递参数存储在被调用方对象中,然后被调用方删除时会发生什么情况
- 当我在 C++ 中对未初始化的指针调用"delete"时会发生什么情况?
- 如果在其他线程仍在运行时调用exit(0),会发生什么情况
- 在什么情况下,都不会调用c++析构函数
- 在什么情况下会调用类型的转换运算符?
- 若编译器内联通过函数指针调用的函数,会发生什么情况
- 如果使用错误的格式字符串调用 printf,会发生什么情况
- 如果我在使用新的和结束的程序分配数据后没有调用删除运算符,会发生什么情况?