如果struct包含DateTime字段,为什么LayoutKind.Sequential的工作方式不同?
请考虑以下代码(必须使用"unsafe"启用的编译器应用程序):
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication3
{
static class Program
{
static void Main()
{
Inner test = new Inner();
unsafe
{
Console.WriteLine("Address of struct = " + ((int)&test).ToString("X"));
Console.WriteLine("Address of First = " + ((int)&test.First).ToString("X"));
Console.WriteLine("Address of NotFirst = " + ((int)&test.NotFirst).ToString("X"));
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Inner
{
public byte First;
public double NotFirst;
public DateTime WTF;
}
}
Run Code Online (Sandbox Code Playgroud)
现在如果我运行上面的代码,我得到类似于以下的输出:
struct = 40F2CC的
地址First = 40F2D4的
地址NotFirst的地址= 40F2CC
注意,First的地址与struct的地址不同; 然而,NotFirst的地址是一样的结构的地址.
现在注释掉结构中的"DateTime WTF"字段,然后再次运行它.这一次,我得到的输出类似于:
struct …
当我用Google搜索时,我看到帖子说传递C#class与ref struct使用PInvoke时传递给C API 相同(这里是一个帖子C#PInvoke struct vs class access violation).
但是,在运行示例时,我看到的行为与预期不同.在ref struct"类"中没有作为真正指针的地方
C代码:
//PInvokeProvider.h
#include "stdafx.h"
typedef struct Animal_s
{
char Name[10000];
} Animal;
extern "C" void __declspec(dllexport) ChangeName(Animal* pAnimal);
//PInvokeProvider.cpp
#include "stdafx.h"
#include <stdio.h>
#include "PInvokeProvider.h"
extern "C" {
void ChangeName(Animal* pAnimal)
{
printf("Entered C++\n");
printf("Recieved animal : %s\n", pAnimal->Name);
printf("This function will change the first letter of animal to 'A'\n");
pAnimal->Name[0] = 'A';
printf("Animal changed to : %s\n", pAnimal->Name);
printf("Leaving C++\n"); …Run Code Online (Sandbox Code Playgroud) 我遇到了一个奇怪的场景,它在C#/ .NET中包含了包含数组的联合.考虑以下程序:
namespace Marshal
{
class Program
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct InnerType
{
byte Foo;
//[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
//byte[] Bar;
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct UnionType
{
[FieldOffset(0)]
InnerType UnionMember1;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
byte[] UnionMember2;
}
static void Main(string[] args)
{
Console.WriteLine(@"SizeOf UnionType: {0}", System.Runtime.InteropServices.Marshal.SizeOf(typeof(UnionType)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您运行此程序,您将获得以下异常:
Could not load type 'UnionType' from assembly 'Marshal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset …Run Code Online (Sandbox Code Playgroud)