--- /dev/null
+#include "platformdefines.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <xplatform.h>
+
+typedef void *voidPtr;
+
+struct SeqClass
+{
+ int a;
+ bool b;
+ char* str;
+};
+
+struct ExpClass
+{
+ int a;
+ int extra; //padding needs to be added here as we have added 8 byte offset.
+ union
+ {
+ int i;
+ BOOL b;
+ double d;
+ } udata;
+};
+
+struct BlittableClass
+{
+ int a;
+};
+
+struct NestedLayoutClass
+{
+ SeqClass str;
+};
+
+extern "C"
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleSeqLayoutClassByRef(SeqClass *p)
+{
+ if((p->a != 0) || (p->b) || strcmp(p->str, "before") != 0)
+ {
+ printf("\np->a=%d, p->b=%s, p->str=%s", p->a, p->b ? "true" : "false", p->str);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C"
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByRef(BlittableClass *p)
+{
+ if(p->a != 10)
+ {
+ printf("\np->a=%d", p->a);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C"
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleExpLayoutClassByRef(ExpClass *p)
+{
+ if((p->a != 0) || (p->udata.i != 10))
+ {
+ printf("\np->a=%d, p->udata.i=%d\n",p->a,p->udata.i);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleNestedLayoutClassByValue(NestedLayoutClass v)
+{
+ return SimpleSeqLayoutClassByRef(&v.str);
+}
--- /dev/null
+using System;
+using System.Security;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+namespace PInvokeTests
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public class SeqClass
+ {
+ public int a;
+ public bool b;
+ public string str;
+
+ public SeqClass(int _a, bool _b, string _str)
+ {
+ a = _a;
+ b = _b;
+ str = String.Concat(_str, "");
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public class ExpClass
+ {
+ [FieldOffset(0)]
+ public DialogResult type;
+
+ [FieldOffset(8)]
+ public int i;
+
+ [FieldOffset(8)]
+ public bool b;
+
+ [FieldOffset(8)]
+ public double c;
+
+ public ExpClass(DialogResult t, int num)
+ {
+ type = t;
+ b = false;
+ c = num;
+ i = num;
+ }
+ public ExpClass(DialogResult t, double dnum)
+ {
+ type = t;
+ b = false;
+ i = 0;
+ c = dnum;
+ }
+ public ExpClass(DialogResult t, bool bnum)
+ {
+ type = t;
+ i = 0;
+ c = 0;
+ b = bnum;
+ }
+ }
+
+ public enum DialogResult
+ {
+ None = 0,
+ OK = 1,
+ Cancel = 2
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class Blittable
+ {
+ public int a;
+
+ public Blittable(int _a)
+ {
+ a = _a;
+ }
+ }
+
+ public struct NestedLayout
+ {
+ public SeqClass value;
+ }
+
+ class StructureTests
+ {
+ [DllImport("LayoutClassNative")]
+ private static extern bool SimpleSeqLayoutClassByRef(SeqClass p);
+
+ [DllImport("LayoutClassNative")]
+ private static extern bool SimpleExpLayoutClassByRef(ExpClass p);
+
+ [DllImport("LayoutClassNative")]
+ private static extern bool SimpleNestedLayoutClassByValue(NestedLayout p);
+
+ [DllImport("LayoutClassNative")]
+ private static extern bool SimpleBlittableSeqLayoutClassByRef(Blittable p);
+
+ public static bool SequentialClass()
+ {
+ string s = "before";
+ bool retval = true;
+ SeqClass p = new SeqClass(0, false, s);
+
+ TestFramework.BeginScenario("Test #1 Pass a sequential layout class.");
+
+ try
+ {
+ retval = SimpleSeqLayoutClassByRef(p);
+
+ if (retval == false)
+ {
+ TestFramework.LogError("01", "PInvokeTests->SequentialClass : Unexpected error occured on unmanaged side");
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ TestFramework.LogError("04", "Unexpected exception: " + e.ToString());
+ retval = false;
+ }
+
+ return retval;
+ }
+
+ public static bool ExplicitClass()
+ {
+ ExpClass p;
+ bool retval = false;
+
+ TestFramework.BeginScenario("Test #2 Pass an explicit layout class.");
+
+ try
+ {
+ p = new ExpClass(DialogResult.None, 10);
+ retval = SimpleExpLayoutClassByRef(p);
+
+ if (retval == false)
+ {
+ TestFramework.LogError("01", "PInvokeTests->ExplicitClass : Unexpected error occured on unmanaged side");
+ return false;
+ }
+
+ }
+ catch (Exception e)
+ {
+ TestFramework.LogError("03", "Unexpected exception: " + e.ToString());
+ retval = false;
+ }
+
+ return retval;
+ }
+
+ public static bool BlittableClass()
+ {
+ bool retval = true;
+ Blittable p = new Blittable(10);
+
+ TestFramework.BeginScenario("Test #3 Pass a blittable sequential layout class.");
+
+ try
+ {
+ retval = SimpleBlittableSeqLayoutClassByRef(p);
+
+ if (retval == false)
+ {
+ TestFramework.LogError("01", "PInvokeTests->Blittable : Unexpected error occured on unmanaged side");
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ TestFramework.LogError("04", "Unexpected exception: " + e.ToString());
+ retval = false;
+ }
+
+ return retval;
+ }
+
+ public static bool NestedLayoutClass()
+ {
+ string s = "before";
+ bool retval = true;
+ SeqClass p = new SeqClass(0, false, s);
+ NestedLayout target = new NestedLayout
+ {
+ value = p
+ };
+
+ TestFramework.BeginScenario("Test #4 Nested sequential layout class in a structure.");
+
+ try
+ {
+ retval = SimpleNestedLayoutClassByValue(target);
+
+ if (retval == false)
+ {
+ TestFramework.LogError("01", "PInvokeTests->NestedLayoutClass : Unexpected error occured on unmanaged side");
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ TestFramework.LogError("04", "Unexpected exception: " + e.ToString());
+ retval = false;
+ }
+
+ return retval;
+ }
+
+ public static int Main(string[] argv)
+ {
+ bool retVal = true;
+
+ retVal = retVal && SequentialClass();
+ retVal = retVal && ExplicitClass();
+ retVal = retVal && BlittableClass();
+ retVal = retVal && NestedLayoutClass();
+
+ return (retVal ? 100 : 101);
+ }
+
+
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>LayoutClassTest</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+ <OutputType>exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj">
+ <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project>
+ <Name>CoreCLRTestLibrary</Name>
+ </ProjectReference>
+ <ProjectReference Include="CMakeLists.txt"></ProjectReference>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>