473,508 Members | 2,460 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Arrays in structures

I understand that structures are value types and arrays and classes are
reference types. But what about arrays as members of structures i.e. as in
C

struct x
{
int n;
int a[100];
}

How is such a structure (e.g. declared in C++ as a field in a class)
accessed in C#?

Peter Seaman
Nov 15 '05 #1
33 3823
<"Peter Seaman" <Peter MS Seaman at StableSoftware.com>> wrote:
I understand that structures are value types and arrays and classes are
reference types. But what about arrays as members of structures i.e. as in
C

struct x
{
int n;
int a[100];
}

How is such a structure (e.g. declared in C++ as a field in a class)
accessed in C#?


You can't declare it like that in C# - you'd have to declare it as just

int[] a;

and initialise it in a constructor or similar. The struct itself is
still a value type, but the variable a would contain a reference. It's
exactly the same as if you have a struct containing a string reference
or similar.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2
> and initialise it in a constructor or similar. The struct itself is
still a value type, but the variable a would contain a reference. It's
exactly the same as if you have a struct containing a string reference
or similar.


Value types live only on stack, but what with struct containing String
variable?
What will happen with this String when for example we leave function ?
Gawel
Nov 15 '05 #3
Gawelek <ga*****@NOSPAMEKpoczta.gazeta.pl> wrote:
and initialise it in a constructor or similar. The struct itself is
still a value type, but the variable a would contain a reference. It's
exactly the same as if you have a struct containing a string reference
or similar.
Value types live only on stack


No they don't. See
http://www.pobox.com/~skeet/csharp/memory.html
but what with struct containing String variable?
What will happen with this String when for example we leave function ?


It's the same as always: if there are no live references to the string,
it will eventually be garbage collected.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #4
> http://www.pobox.com/~skeet/csharp/memory.html

Thanks, now all is clear.

Gawel
Nov 15 '05 #5
Thanks, so structures containing directly embedded arrays are not possible
in C#. Such structures are possible in other languages such as C++ and I
often use them. What I am still uncertain about is this: if in C++ such a
structure is made a member of a class, can that member be accessed in C# and
if so how?

Peter Seaman
Nov 15 '05 #6
<"Peter Seaman" <Peter MS Seaman at StableSoftware.com>> wrote:
Thanks, so structures containing directly embedded arrays are not possible
in C#.
Not as far as I know, no.
Such structures are possible in other languages such as C++ and I
often use them. What I am still uncertain about is this: if in C++ such a
structure is made a member of a class, can that member be accessed in C# and
if so how?


Well, the first thing to do is test whether it is still possible in
*managed* C++ - and then run ildasm on the created assembly and see
what's in it.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #7
> Well, the first thing to do is test whether it is still possible in
*managed* C++ - and then run ildasm on the created assembly and see
what's in it.


No doubt this is good advice but unfortunately I only have C# Standard.
Though this product does contain Visual Studio 2003 and compilers for
JScript .NET and VB .NET, it does not allow me to compile C++ .NET as far as
I can see.

It seems to me that arrays and structures and combinations of such
aggregates are pretty fundamental to programming, so on the face of this
inability for structures to contain embedded arrays is a severe restriction.
Is there an easy way round it? How does C# cope with the many such
structures in the WIN32 API e.g. LPWIN32_FIND_DATA?

Peter Seaman

Nov 15 '05 #8
<"Peter Seaman" <Peter MS Seaman at StableSoftware.com>> wrote:
Well, the first thing to do is test whether it is still possible in
*managed* C++ - and then run ildasm on the created assembly and see
what's in it.
No doubt this is good advice but unfortunately I only have C# Standard.
Though this product does contain Visual Studio 2003 and compilers for
JScript .NET and VB .NET, it does not allow me to compile C++ .NET as far as
I can see.


Ah. I'm afraid I don't know much managed C++ at all - perhaps another
poster with more experience of it could help us?
It seems to me that arrays and structures and combinations of such
aggregates are pretty fundamental to programming, so on the face of this
inability for structures to contain embedded arrays is a severe restriction.
Is there an easy way round it? How does C# cope with the many such
structures in the WIN32 API e.g. LPWIN32_FIND_DATA?


No idea, I'm afraid :(

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #9

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:uI*************@TK2MSFTNGP11.phx.gbl...
Well, the first thing to do is test whether it is still possible in
*managed* C++ - and then run ildasm on the created assembly and see
what's in it.


No doubt this is good advice but unfortunately I only have C# Standard.
Though this product does contain Visual Studio 2003 and compilers for
JScript .NET and VB .NET, it does not allow me to compile C++ .NET as far
as
I can see.

It seems to me that arrays and structures and combinations of such
aggregates are pretty fundamental to programming, so on the face of this
inability for structures to contain embedded arrays is a severe
restriction.
Is there an easy way round it? How does C# cope with the many such
structures in the WIN32 API e.g. LPWIN32_FIND_DATA?

Peter Seaman


This is not such a problem in C#, following is a sample using FindNexttFile
and WIN32_FIND_DATA.

using System;
using System.Runtime.InteropServices;
namespace Willys
{

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct _WIN32_FIND_DATAW
{
public uint dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
// TCHAR array 260 (MAX_PATH) entries, 520 bytes in unicode
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=520)]
public string cFileName;
// TCHAR array 14 TCHAR's alternate filename 28 byes in unicode
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=28)]
public string cAlternateFileName;
}

[StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
}
class Tester
{
[DllImport("kernel32.dll", EntryPoint="FindFirstFileW", SetLastError=true,
CharSet = CharSet.Unicode)]
public static extern IntPtr FindFirstFileW( string lpFileName, ref
_WIN32_FIND_DATAW lpFindFileData);
static void Main()
{
string file = "*.exe";
_WIN32_FIND_DATAW fndData = new _WIN32_FIND_DATAW();
IntPtr hFile = FindFirstFileW(file, ref fndData);
if(hFile.ToInt32() == -1)
Console.WriteLine("FindFirst: " + Marshal.GetLastWin32Error());
else
Console.WriteLine("Filename: " + fndData.cFileName_260);

}
}
}

Willy.
Nov 15 '05 #10
Thanks for that. Does this technique extend to arrays of other than
bytes/chars? e.g. here is an example from winnt.h of an embedded array of
structures.

typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;

typedef struct _PRIVILEGE_SET {
DWORD PrivilegeCount;
DWORD Control;
LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY];
} PRIVILEGE_SET, * PPRIVILEGE_SET;
Peter Seaman
Nov 15 '05 #11

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:%2***************@TK2MSFTNGP11.phx.gbl...
Thanks for that. Does this technique extend to arrays of other than
bytes/chars? e.g. here is an example from winnt.h of an embedded array of
structures.

typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;

typedef struct _PRIVILEGE_SET {
DWORD PrivilegeCount;
DWORD Control;
LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY];
} PRIVILEGE_SET, * PPRIVILEGE_SET;
Peter Seaman


Sure, here's how to ....

[StructLayout(LayoutKind.Sequential)]
public struct LUID {
public int LowPart;
public int HighPart;
}

[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES {
public LUID Luid;
public int Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct _PRIVILEGE_SET {
public int PrivilegeCount;
public int Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)] // ANYSIZE_ARRAY = 1
public LUID_AND_ATTRIBUTES [] Privileges;
}

However if you consider doing this from C# you might as well just use
Managed C++.

Willy.
Nov 15 '05 #12
Thanks for this which does answer my question. Does the use of these
unmanaged types imply extra overhead (or less overhead) or unsafe code?

Peter Seaman
Nov 15 '05 #13
Sorry, I still don't understand this. When I declare as indicated and
execute

_PRIVILEGE_SET ps = new _PRIVILEGE_SET;

ps.Privileges[0] = 0;

I get

"An unhandled exception of type 'System.NullReferenceException' occurred
....Additional information: Object reference not set to an instance of an
object."

But if I say ps.Privileges = new LUID_AND_ATTRIBUTES[1]; I assume I get a
separate array outside the structure, is that correct?

Peter Seaman

Nov 15 '05 #14

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:uB*************@TK2MSFTNGP09.phx.gbl...
Sorry, I still don't understand this. When I declare as indicated and
execute

_PRIVILEGE_SET ps = new _PRIVILEGE_SET;

ps.Privileges[0] = 0;

I get

"An unhandled exception of type 'System.NullReferenceException' occurred
...Additional information: Object reference not set to an instance of an
object."

But if I say ps.Privileges = new LUID_AND_ATTRIBUTES[1]; I assume I get a
separate array outside the structure, is that correct?

Peter Seaman

ps.Privileges denotes a structure array! you can't set an element (a stuct)
to 0, you can only set values to the members of the struct
ps.Privileges[0].Luid = ...
ps.Privileges[0].Attributes= ...

Willy.
Nov 15 '05 #15
Yes of course. I did actually say ps.Privileges[0].Attributes = 0; but
mis-typed the code above.

PRIVILEGE_SET ps = new _PRIVILEGE_SET;
ps.Privileges[0].Attributes = 0;

Gives the null reference exception.

I remain unclear on how these embedded arrays are supposed to work. Does
ps.Privileges = new LUID_AND_ATTRIBUTES[1] give an array inside the
structure on the stack or outside the structure on the heap?

Peter Seaman


Nov 15 '05 #16

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:eS**************@TK2MSFTNGP12.phx.gbl...
Yes of course. I did actually say ps.Privileges[0].Attributes = 0; but
mis-typed the code above.

PRIVILEGE_SET ps = new _PRIVILEGE_SET;
ps.Privileges[0].Attributes = 0;


Peter,

Not exactly sure what you want to use the Privileges for, but following is a
small sample that illustrates how you check security privileges using
embedded structs in C# (whithout using usafe code).
But again I would never use C# for this, this is realy the domain of the
Managed Extensions for C++ .

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Willys
{
[StructLayout(LayoutKind.Sequential)]
public struct _PRIVILEGE_SET
{
public uint PrivilegeCount;
public uint Control;
public LUID_AND_ATTRIBUTES Privilege_1; // Only one struct anyway, so no
array declaration
}

[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public uint HighPart;
}
public sealed class StructInspector
{
// dump serialized object or struct
public static void DisplayStruct(Object o)
{
const int bytesPerLinen = 16;
int totalBytes = Marshal.SizeOf(o);
Console.WriteLine("Size of object: " + totalBytes);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocCoTaskMem(totalBytes);
Marshal.StructureToPtr(o, ptr, false);
byte[] bytes = new byte[bytesPerLinen];
for (int i = 0; i < totalBytes; i += bytesPerLinen )
{
for (int j = 0;j < bytesPerLinen ; j++)
{
if (i + j < totalBytes)
{
bytes[j] = Marshal.ReadByte(ptr, i+j);
Console.Write("{0:x2} ", bytes[j]);

} else
{
Console.Write(" ");
}
}

Console.Write(" ");
for (int j = 0;j < bytesPerLinen && i + j < totalBytes ; j++ )
{
if (bytes[j] < 32)
Console.Write(".");
else
Console.Write(Convert.ToChar(bytes[j]));
}
Console.WriteLine("");
}
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(ptr);
}
}
}
}
class Tester
{

[DllImport("advapi32.dll", EntryPoint="PrivilegeCheck", SetLastError=true)]
public static extern bool PrivilegeCheck( IntPtr ClientToken, ref
_PRIVILEGE_SET RequiredPrivileges, ref int pfResult);

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public extern static bool LookupPrivilegeValue(string lpSystemName,
string lpName, ref LUID pLuid);

public const int PRIVILEGE_SET_ALL_NECESSARY = 1;
static void Main()
{
int result = 0;
IntPtr hToken;
// Setting up the PRIVILEGE_SET to contain "SeImpersonatePrivilege"
_PRIVILEGE_SET ps = new _PRIVILEGE_SET();
ps.PrivilegeCount = 1;
ps.Control = PRIVILEGE_SET_ALL_NECESSARY; // or 0 if any of
if (!LookupPrivilegeValue(null, "SeImpersonatePrivilege", ref
ps.Privilege_1.Luid))
{
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());

}
StructInspector.DisplayStruct(ps);

WindowsIdentity.Impersonate(WindowsIdentity.GetCur rent().Token);
hToken = WindowsIdentity.GetCurrent().Token;
Console.WriteLine("Token used: " + hToken);
if(!PrivilegeCheck(hToken, ref ps, ref result))
Console.WriteLine("<PrivilegeCheck> Win32 Error {0}",
Marshal.GetLastWin32Error());
Console.WriteLine("Privilege set '{0}'", Convert.ToBoolean(result));
StructInspector.DisplayStruct(ps);
}
}
}

Willy.

Nov 15 '05 #17
Sorry this is not helpful because you have now removed the array. My
reaction is Wow!!! I am afraid my enthusiasm for C# is somewhat diminished.

I only wanted to know how to use the simple structure in my original
message - a structure containing an integer followed by an array of
integers. This is a common construct in my world and I only quoted
"Privileges" as an example of a similar structure in the Win32 API.

Can anyone answer the simple question asked for the second time in my last
message: if you declare an embedded array (by using MarshalAs) how do you
reference the elements of the array and what happens when you "new" it?

Peter Seaman
Nov 15 '05 #18
Yes, I removed the array declaration because the size is 1 (ANYSIZE_ARRAY)
in the sample.
The problem with embedded arrays and variable length structures is realated
to the Interop marshaller, not C#.
The current version of the marshaller cannot handle them, to solve this you
have a number of options:
- Use Managed C++ which, as I told you, is THE interop language in .NET,
there are way too many opportunities to make mistakes while porting C/C++
header files to C# P/Invoke signatures.
- Pass managed pointers pointing to native memory (alloacted with
Marshal.AllocHGlobal or Marshal.AllocCoTaskMem) the API's and use
Marshal.StructureToPtr and Marshal.PtrToStructure to access the struct
fields before and after the call ( this is why I included StructInspector()
in the sample to get you started).
- Use unsafe code blocks and pointers.
- Flatten the structure and use arryays of blittable types to replace the
embedded struct array's, here's a sample.

note: non of the options (except MC++) solve the problem of marshalling
variable length structs.).

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Willys
{

[StructLayout(LayoutKind.Sequential)]

public struct _PRIVILEGE_SET
{
public uint PrivilegeCount;
public uint Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] // 2 privilege
structs flatten to be 6 int's !!!!
public int[] Privilege_1;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint Attributes;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID
{
public uint LowPart;
public uint HighPart;
}

public sealed class StructInspector
{
.......// see previous posting

}
class Tester
{

[DllImport("advapi32.dll", EntryPoint="PrivilegeCheck", SetLastError=true)]
public static extern bool PrivilegeCheck( IntPtr ClientToken, ref
_PRIVILEGE_SET RequiredPrivileges, ref int pfResult);

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public extern static bool LookupPrivilegeValue(string lpSystemName, string
lpName, ref int pLuid);

public const int PRIVILEGE_SET_ALL_NECESSARY = 1;
static void Main()
{
int result = 0;
IntPtr hToken;
uint privCount = 2;
// Setting up the PRIVILEGE_SET to contain "SeImpersonatePrivilege" and
"SeChangeNotifyPrivilege"
_PRIVILEGE_SET ps = new _PRIVILEGE_SET();
ps.PrivilegeCount = privCount;
ps.Privilege_1 = new int[privCount * 3]; // allocate 2 * 3 int's each
privilege takes 3 int's)
ps.Control = PRIVILEGE_SET_ALL_NECESSARY ; // or 0 if any of
if (!LookupPrivilegeValue(null, "SeImpersonatePrivilege",ref
ps.Privilege_1[0]))
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());
if (!LookupPrivilegeValue(null, "SeChangeNotifyPrivilege",ref
ps.Privilege_1[3]))
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());
StructInspector.DisplayStruct(ps);

WindowsIdentity.Impersonate(WindowsIdentity.GetCur rent().Token);
hToken = WindowsIdentity.GetCurrent().Token;
Console.WriteLine("Token used: " + hToken);
if(!PrivilegeCheck(hToken, ref ps, ref result))
Console.WriteLine("<PrivilegeCheck> Win32 Error {0}",
Marshal.GetLastWin32Error());
Console.WriteLine("Privilege set '{0}'", Convert.ToBoolean(result));
StructInspector.DisplayStruct(ps);
}
}
}

Willy.
"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Sorry this is not helpful because you have now removed the array. My
reaction is Wow!!! I am afraid my enthusiasm for C# is somewhat
diminished.

I only wanted to know how to use the simple structure in my original
message - a structure containing an integer followed by an array of
integers. This is a common construct in my world and I only quoted
"Privileges" as an example of a similar structure in the Win32 API.

Can anyone answer the simple question asked for the second time in my last
message: if you declare an embedded array (by using MarshalAs) how do you
reference the elements of the array and what happens when you "new" it?

Peter Seaman

Nov 15 '05 #19
> The problem with embedded arrays and variable length structures is
realated
to the Interop marshaller, not C#. The current version of the marshaller

cannot handle them,
Nov 15 '05 #20
> The problem with embedded arrays and variable length structures
is related to the Interop marshaller, not C#.


What about my original example: a fixed length structure containing a fixed
Nov 15 '05 #21
> The problem with embedded arrays and variable length structures is related
to the Interop marshaller, not C#. The current version of the marshaller cannot handle them


What about my example of a FIXED length structure containing a FIXED
length array?

Peter Seaman
Nov 15 '05 #22
Peter,
I am embedding an arraylist within a struct in C# that is then is wrapped
for a COM-base client... My code looks like this:

#region Build structs

//Build structs for processing feature classes.

//This enables method overloading.
public struct stmatch

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

}
public struct stmatchwhere

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

public string WhereClause;

}
public struct stmatchsubtype

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

}
public struct stmatchall

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

public string WhereClause;

}
public struct stnomatch

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

}
public struct stnomatchsubtype

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

public string sSubType;

}
public struct stnomatchwhere

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

public string WhereClause;

}
public struct stnomatchall

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

public string sSubType;

public string WhereClause;

}

#endregion

//Now add arraylists to each struct...

// Setup list of feature classes (tables) with associated array of arcfm
tables

SortedList slFeatureClasses = new SortedList();

ArrayList alArcFMTables = new ArrayList();
//Add arraylist of arcfm tables to sorted list of sde tables

alArcFMTables.Add("gis_elec.abandonedelectriclines egment");

alArcFMTables.Add("gis_elec.conduitsystem");

alArcFMTables.Add("gis_elec.priohelectriclinesegme nt");

alArcFMTables.Add("gis_elec.priugelectriclinesegme nt");

alArcFMTables.Add("gis_elec.secohelectriclinesegme nt");

alArcFMTables.Add("gis_elec.secugelectriclinesegme nt");

slFeatureClasses.Add(conElCableLine, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.anchorguy");

alArcFMTables.Add("gis_elec.pushbrace");

slFeatureClasses.Add(conUtGuyPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.conduitsystem");

slFeatureClasses.Add(conElDuctBankLine, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.electricstation");

slFeatureClasses.Add(conElSubStationSite, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.generator");

slFeatureClasses.Add(conElGenPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.primarymeter");

slFeatureClasses.Add(conElMeterPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.riser");

slFeatureClasses.Add(conElRiserPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.switch");

alArcFMTables.Add("gis_elec.switchingfacility");

slFeatureClasses.Add(conElSwitchPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.transformer");

slFeatureClasses.Add(conElTransBnkPnt, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.undergroundstructure") ;

slFeatureClasses.Add(conElJuncPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.streetlight");

slFeatureClasses.Add(conExLightPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.supportstructure");

slFeatureClasses.Add(conUtPoleTowerPoint, alArcFMTables);

This should clear it all up for you 8-)... enjoy.

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Sorry this is not helpful because you have now removed the array. My
reaction is Wow!!! I am afraid my enthusiasm for C# is somewhat diminished.
I only wanted to know how to use the simple structure in my original
message - a structure containing an integer followed by an array of
integers. This is a common construct in my world and I only quoted
"Privileges" as an example of a similar structure in the Win32 API.

Can anyone answer the simple question asked for the second time in my last
message: if you declare an embedded array (by using MarshalAs) how do you
reference the elements of the array and what happens when you "new" it?

Peter Seaman

Nov 15 '05 #23
Peter,
I am embedding an arraylist within a struct in C# that is then is wrapped
for a COM-base client... My code looks like this:

#region Build structs

//Build structs for processing feature classes.

//This enables method overloading.
public struct stmatch

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

}
public struct stmatchwhere

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

public string WhereClause;

}
public struct stmatchsubtype

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

}
public struct stmatchall

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

public string WhereClause;

}
public struct stnomatch

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

}
public struct stnomatchsubtype

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

public string sSubType;

}
public struct stnomatchwhere

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

public string WhereClause;

}
public struct stnomatchall

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string outSubFields;

public string inSubFields;

public string sSubType;

public string WhereClause;

}

#endregion

//Now add arraylists to each struct...

// Setup list of feature classes (tables) with associated array of arcfm
tables

SortedList slFeatureClasses = new SortedList();

ArrayList alArcFMTables = new ArrayList();
//Add arraylist of arcfm tables to sorted list of sde tables

alArcFMTables.Add("gis_elec.abandonedelectriclines egment");

alArcFMTables.Add("gis_elec.conduitsystem");

alArcFMTables.Add("gis_elec.priohelectriclinesegme nt");

alArcFMTables.Add("gis_elec.priugelectriclinesegme nt");

alArcFMTables.Add("gis_elec.secohelectriclinesegme nt");

alArcFMTables.Add("gis_elec.secugelectriclinesegme nt");

slFeatureClasses.Add(conElCableLine, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.anchorguy");

alArcFMTables.Add("gis_elec.pushbrace");

slFeatureClasses.Add(conUtGuyPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.conduitsystem");

slFeatureClasses.Add(conElDuctBankLine, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.electricstation");

slFeatureClasses.Add(conElSubStationSite, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.generator");

slFeatureClasses.Add(conElGenPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.primarymeter");

slFeatureClasses.Add(conElMeterPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.riser");

slFeatureClasses.Add(conElRiserPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.switch");

alArcFMTables.Add("gis_elec.switchingfacility");

slFeatureClasses.Add(conElSwitchPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.transformer");

slFeatureClasses.Add(conElTransBnkPnt, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.undergroundstructure") ;

slFeatureClasses.Add(conElJuncPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.streetlight");

slFeatureClasses.Add(conExLightPoint, alArcFMTables);
alArcFMTables = new ArrayList();

alArcFMTables.Add("gis_elec.supportstructure");

slFeatureClasses.Add(conUtPoleTowerPoint, alArcFMTables);

This should clear it all up for you 8-)... enjoy.

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Sorry this is not helpful because you have now removed the array. My
reaction is Wow!!! I am afraid my enthusiasm for C# is somewhat diminished.
I only wanted to know how to use the simple structure in my original
message - a structure containing an integer followed by an array of
integers. This is a common construct in my world and I only quoted
"Privileges" as an example of a similar structure in the Win32 API.

Can anyone answer the simple question asked for the second time in my last
message: if you declare an embedded array (by using MarshalAs) how do you
reference the elements of the array and what happens when you "new" it?

Peter Seaman

Nov 15 '05 #24
My apologies, copied wrong code...

I set up structs for overloading, then embed complex objects i.e.
sortedlist/arraylist, yikes. Here's a small snippet.

//Build structs for processing feature classes.

//This enables method overloading.
public struct stmatch

{

[MarshalAs(UnmanagedType.Interface)]

public IWorkspace pWorkspace;

public string OutTable;

public string InTable;

public string SubFields;

public string sSubType;

}

const string conElCableLine = "electrical_cable_line";

// Setup list of feature classes (tables) with associated array of arcfm
tables

SortedList slFeatureClasses = new SortedList();

ArrayList alArcFMTables = new ArrayList();

//Add arraylist of arcfm tables to sorted list of sde tables

alArcFMTables.Add("gis_elec.abandonedelectriclines egment");

alArcFMTables.Add("gis_elec.conduitsystem");

alArcFMTables.Add("gis_elec.priohelectriclinesegme nt");

alArcFMTables.Add("gis_elec.priugelectriclinesegme nt");

alArcFMTables.Add("gis_elec.secohelectriclinesegme nt");

alArcFMTables.Add("gis_elec.secugelectriclinesegme nt");

slFeatureClasses.Add(conElCableLine, alArcFMTables);

//-----Loop over each SDE feature class.

for ( int i = 0; i < slFeatureClasses.Count; i++)

{

ArrayList myAL = new ArrayList();

//-----Set an arraylist for the current feature class (key)

myAL = (ArrayList) slFeatureClasses.GetByIndex(i);

//-----Declare an arraylist for in and out fields.

ArrayList alInFields = new ArrayList();

ArrayList alOutFields = new ArrayList();

for ( int n = 0; n < myAL.Count; n++)

{

pPro.Message = "Loading " + myAL[n].ToString() + " to " + user +"." +
slFeatureClasses.GetKey(i).ToString() + ".";

switch(slFeatureClasses.GetKey(i).ToString())

{

case conElCableLine:

switch(myAL[n].ToString())

{

case "gis_elec.abandonedelectriclinesegment":

//THIS IS WHERE I USE THE STRUCT-------------------------------

istmatchall = new stmatchall();

istmatchall.InTable = myAL[n].ToString();

istmatchall.OutTable = user +"." + slFeatureClasses.GetKey(i).ToString();

istmatchall.pWorkspace = pWorkspace;

istmatchall.sSubType = "ABANDONED";

istmatchall.SubFields = "shape,instln_id,user_flag";

istmatchall.WhereClause = "WHERE inconduitindicator = 'no'";

//CALL MY OVERLOADED FUNCTION HERE(pass in struct)--------------------

ObjectLoader(istmatchall);

break;

}

}

}

}


Regards,

Jeff

"Willy Denoyette [MVP]" <wi*************@pandora.be> wrote in message
news:uT**************@tk2msftngp13.phx.gbl...
Yes, I removed the array declaration because the size is 1 (ANYSIZE_ARRAY)
in the sample.
The problem with embedded arrays and variable length structures is realated to the Interop marshaller, not C#.
The current version of the marshaller cannot handle them, to solve this you have a number of options:
- Use Managed C++ which, as I told you, is THE interop language in .NET,
there are way too many opportunities to make mistakes while porting C/C++
header files to C# P/Invoke signatures.
- Pass managed pointers pointing to native memory (alloacted with
Marshal.AllocHGlobal or Marshal.AllocCoTaskMem) the API's and use
Marshal.StructureToPtr and Marshal.PtrToStructure to access the struct
fields before and after the call ( this is why I included StructInspector() in the sample to get you started).
- Use unsafe code blocks and pointers.
- Flatten the structure and use arryays of blittable types to replace the
embedded struct array's, here's a sample.

note: non of the options (except MC++) solve the problem of marshalling
variable length structs.).

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Willys
{

[StructLayout(LayoutKind.Sequential)]

public struct _PRIVILEGE_SET
{
public uint PrivilegeCount;
public uint Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] // 2 privilege
structs flatten to be 6 int's !!!!
public int[] Privilege_1;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint Attributes;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID
{
public uint LowPart;
public uint HighPart;
}

public sealed class StructInspector
{
......// see previous posting

}
class Tester
{

[DllImport("advapi32.dll", EntryPoint="PrivilegeCheck", SetLastError=true)] public static extern bool PrivilegeCheck( IntPtr ClientToken, ref
_PRIVILEGE_SET RequiredPrivileges, ref int pfResult);

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public extern static bool LookupPrivilegeValue(string lpSystemName, string lpName, ref int pLuid);

public const int PRIVILEGE_SET_ALL_NECESSARY = 1;
static void Main()
{
int result = 0;
IntPtr hToken;
uint privCount = 2;
// Setting up the PRIVILEGE_SET to contain "SeImpersonatePrivilege" and
"SeChangeNotifyPrivilege"
_PRIVILEGE_SET ps = new _PRIVILEGE_SET();
ps.PrivilegeCount = privCount;
ps.Privilege_1 = new int[privCount * 3]; // allocate 2 * 3 int's each privilege takes 3 int's)
ps.Control = PRIVILEGE_SET_ALL_NECESSARY ; // or 0 if any of
if (!LookupPrivilegeValue(null, "SeImpersonatePrivilege",ref
ps.Privilege_1[0]))
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());
if (!LookupPrivilegeValue(null, "SeChangeNotifyPrivilege",ref
ps.Privilege_1[3]))
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());
StructInspector.DisplayStruct(ps);

WindowsIdentity.Impersonate(WindowsIdentity.GetCur rent().Token);
hToken = WindowsIdentity.GetCurrent().Token;
Console.WriteLine("Token used: " + hToken);
if(!PrivilegeCheck(hToken, ref ps, ref result))
Console.WriteLine("<PrivilegeCheck> Win32 Error {0}",
Marshal.GetLastWin32Error());
Console.WriteLine("Privilege set '{0}'", Convert.ToBoolean(result));
StructInspector.DisplayStruct(ps);
}
}
}

Willy.
"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Sorry this is not helpful because you have now removed the array. My
reaction is Wow!!! I am afraid my enthusiasm for C# is somewhat
diminished.

I only wanted to know how to use the simple structure in my original
message - a structure containing an integer followed by an array of
integers. This is a common construct in my world and I only quoted
"Privileges" as an example of a similar structure in the Win32 API.

Can anyone answer the simple question asked for the second time in my last message: if you declare an embedded array (by using MarshalAs) how do you reference the elements of the array and what happens when you "new" it?

Peter Seaman


Nov 15 '05 #25
Thanks, but where is the structure with a directly embedded array?
ArrayLists are completely different things.

I am only asking for something simple, how to use in C# a fixed extent
single dimension array directly embedded in a simple structure. Such
constructs are widely used and have been available in many other languages
for donkeys years. Everybody seems to be mis-interpreting my question
and/or making things exceedingly complicated!

Let me repeat the question. Consider the C structure

struct x
{
int n;
int a[10];
}

Can such a structure be declared in C#, and used for example as a field in a
class, or read from a file? If so, what has to be coded in order to access
the array elements as a[0] a[1]..... a[9]. If it is not possible without
horrendous complications and/or unsafe code please can someone say so.

Peter Seaman
Nov 15 '05 #26

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:uM**************@TK2MSFTNGP09.phx.gbl...
The problem with embedded arrays and variable length structures is
related
to the Interop marshaller, not C#. The current version of the marshaller

cannot
handle them


What about my example of a FIXED length structure containing a FIXED
length array?

Peter Seaman


The marshaller cannot handle "embedded arrays of structures" and "variable
length structs". It can only handle embedded arrays of blittable types(int,
char etc) - as I illustrated in a previous post.
If you really want to use C# to pass such managed structures to unmanaged
code, you'll need to help the marshaller by passing as argument to the API,
a pointer to a buffer, that contains a copy of the managed struct fields you
marshalled using the Marshal.WriteXX methods. On return you need to copy the
buffer contents back to the managed structure using the Marshal.ReadXX
methods. But again why would you do this in C#.

Following illustrates this technique, using two privileges.

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Willys
{

[StructLayout(LayoutKind.Sequential)]

public struct _PRIVILEGE_SET
{
public uint PrivilegeCount;
public uint Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public LUID_AND_ATTRIBUTES[] Privilege_1;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint Attributes;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID
{
public uint LowPart;
public uint HighPart;
}

public sealed class StructInspector
{
// dump serialized object or struct
public static void DisplayStruct(_PRIVILEGE_SET ps)
{
Console.WriteLine("Privileges: {0}",ps.PrivilegeCount);
Console.WriteLine("Control : {0}",ps.Control);
for(int i = 0; i < ps.PrivilegeCount; i++)
{
Console.WriteLine("----------------");
Console.WriteLine("LUID.Low {0:x2}
",ps.Privilege_1[i].Luid.LowPart);
Console.WriteLine("LUID.High {0:x2}
",ps.Privilege_1[i].Luid.HighPart);
Console.WriteLine("Attributes {0:x2} ",ps.Privilege_1[i].Attributes);

}
}

}
class Tester
{

[DllImport("advapi32.dll", EntryPoint="PrivilegeCheck", SetLastError=true)]
public static extern bool PrivilegeCheck( IntPtr ClientToken, IntPtr
RequiredPrivileges, ref int pfResult);

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public extern static bool LookupPrivilegeValue(string lpSystemName, string
lpName, IntPtr pLuid);

public const int PRIVILEGE_SET_ALL_NECESSARY = 1;
static void Main()
{
int result = 0;
IntPtr hToken;
uint privCount = 2;

// Setting up the PRIVILEGE_SET to contain "SeImpersonatePrivilege" and
"SeChangeNotifyPrivilege"
_PRIVILEGE_SET ps = new _PRIVILEGE_SET();

ps.PrivilegeCount = privCount;
ps.Privilege_1 = new LUID_AND_ATTRIBUTES[2];
ps.Control = PRIVILEGE_SET_ALL_NECESSARY; // or 0 if any of
int privSize = Marshal.SizeOf(ps.Privilege_1[0]);
IntPtr ptr = IntPtr.Zero;
ptr = Marshal.AllocCoTaskMem(privSize * (int)privCount);

Marshal.StructureToPtr(ps.Privilege_1[0], ptr, false);
if (!LookupPrivilegeValue(null, "SeImpersonatePrivilege",ptr))
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());
ps.Privilege_1[0] =
(LUID_AND_ATTRIBUTES)Marshal.PtrToStructure(ptr,ty peof(LUID_AND_ATTRIBUTES));

Marshal.StructureToPtr(ps.Privilege_1[1], (IntPtr)((int)ptr + privSize),
false);
if (!LookupPrivilegeValue(null,
"SeChangeNotifyPrivilege",(IntPtr)((int)ptr + privSize)))
Console.WriteLine("<LookupPrivilegeValue> Win32 Error {0}",
Marshal.GetLastWin32Error());
ps.Privilege_1[1] =
(LUID_AND_ATTRIBUTES)Marshal.PtrToStructure((IntPt r)((int)ptr +
privSize),typeof(LUID_AND_ATTRIBUTES));
Marshal.FreeCoTaskMem(ptr); // Free alocated mem

IntPtr ptrPs = IntPtr.Zero;
ptrPs = Marshal.AllocHGlobal(64); // 64 byte buffer
Marshal.WriteInt32(ptrPs,(int)ps.PrivilegeCount);
Marshal.WriteInt32((IntPtr)((int)ptrPs + 4),(int)ps.Control);
Marshal.StructureToPtr(ps.Privilege_1[0],(IntPtr)((int) ptrPs + 8),
false);
Marshal.StructureToPtr(ps.Privilege_1[1],(IntPtr)((int) ptrPs + 20),
false);

WindowsIdentity.Impersonate(WindowsIdentity.GetCur rent().Token);
hToken = WindowsIdentity.GetCurrent().Token;
Console.WriteLine("Token used: " + hToken);
if(!PrivilegeCheck(hToken, ptrPs, ref result))
Console.WriteLine("<PrivilegeCheck> Win32 Error {0}",
Marshal.GetLastWin32Error());
ps.PrivilegeCount = (uint)Marshal.ReadInt32(ptrPs);
ps.Control = (uint)Marshal.ReadInt32(ptrPs, 4);
ps.Privilege_1[0] =
(LUID_AND_ATTRIBUTES)Marshal.PtrToStructure((IntPt r)((int)ptrPs +
8),typeof(LUID_AND_ATTRIBUTES));
ps.Privilege_1[1] =
(LUID_AND_ATTRIBUTES)Marshal.PtrToStructure((IntPt r)((int)ptrPs +
20),typeof(LUID_AND_ATTRIBUTES));

Marshal.FreeHGlobal( ptrPs ); // Free allocated mem
Console.WriteLine("Privilege's set '{0}'", Convert.ToBoolean(result));
StructInspector.DisplayStruct(ps);
}
}
}

Willy.
Nov 15 '05 #27
using System;

using System.Runtime.InteropServices;

using System.Diagnostics;

namespace MyNameSpace

{

/// <summary>

/// Summary description for Class2.

/// </summary>

public class myClass

{
public static void Main(string[] Args)

{

myClass o = new myClass();

}
public struct myStruct

{

public string[] sArray;

public myStruct(int i)

{

sArray = new string[i];

}

}

public myClass()

{

//

// TODO: Add constructor logic here

//

myStruct useStruct = new myStruct(10);

for ( int i = 0; i < 10; i++)

{

useStruct.sArray[i] = System.Convert.ToString(i);

Debug.WriteLine(useStruct.sArray[i].ToString());

}

}

}

}

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:On*************@TK2MSFTNGP11.phx.gbl...
Thanks, but where is the structure with a directly embedded array?
ArrayLists are completely different things.

I am only asking for something simple, how to use in C# a fixed extent
single dimension array directly embedded in a simple structure. Such
constructs are widely used and have been available in many other languages
for donkeys years. Everybody seems to be mis-interpreting my question
and/or making things exceedingly complicated!

Let me repeat the question. Consider the C structure

struct x
{
int n;
int a[10];
}

Can such a structure be declared in C#, and used for example as a field in a class, or read from a file? If so, what has to be coded in order to access the array elements as a[0] a[1]..... a[9]. If it is not possible without
horrendous complications and/or unsafe code please can someone say so.

Peter Seaman

Nov 15 '05 #28
I am afraid this is not an embedded array. The array data is outside the
structure on the heap and your example does not therefore achieve what is
required. (One way to verify this is to take a simple (i.e. shallow) copy
of useStruct.)

Peter Seaman


Nov 15 '05 #29
> If you really want to use C# to pass such managed structures to
unmanaged code


But I did not say I wanted to do this! All I want is the ability to
declare and use a structure containing a directly embedded array, i.e. an
array whose data is part of the structure not outside it. There are various
consequences, for example, copying the structure would necessarily copy all
the array data as well. I only quoted the Win32 FIND_DATA and PRIVILEGE SET
examples as evidence for my claim that such structures are not unsual.

I conclude that this simple and common requirement is not met in C#, and I
contend that this a defect of the language. Of course you can program round
it in various clumsy ways, just as you can program round not using
structures at all.

Peter Seaman
Nov 15 '05 #30
Ok, I'm getting confused, do you need to pass your structures to unmanaged
code API's?
If your answer is YES, there are no other way's I showed you to do it for
now.

If you DON'T need to pass the structure to unmanaged code, you can declare
your structures with embedded structure array's, however, there is no
reason to do this, in .NET structures are value types and you should only
use them when for data items which have "value" semantics and are "small"
(System.Decimal is a good sample).

If you still want to use structures in C# ( instead of classes) with
embedded arrays of structs, and you don't want to pass these to unmanaged
code, look at (and run) the following sample:

using System;
using System.Runtime.InteropServices;
namespace Willys
{

[StructLayout(LayoutKind.Sequential)]

public struct _PRIVILEGE_SET
{
public uint PrivilegeCount;
public uint Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public LUID_AND_ATTRIBUTES[] Privilege_1;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public uint Attributes;
}

[StructLayout(LayoutKind.Sequential)]

public struct LUID
{
public uint LowPart;
public uint HighPart;
}

public sealed class StructInspector
{
// dump serialized object or struct
public static void DisplayStruct(_PRIVILEGE_SET ps)
{
Console.WriteLine("Privileges: {0}",ps.PrivilegeCount);
Console.WriteLine("Control : {0}",ps.Control);
for(int i = 0; i < ps.PrivilegeCount; i++)
{
Console.WriteLine("----------------");
Console.WriteLine("LUID.Low {0:x2}
",ps.Privilege_1[i].Luid.LowPart);
Console.WriteLine("LUID.High {0:x2}
",ps.Privilege_1[i].Luid.HighPart);
Console.WriteLine("Attributes {0:x2} ",ps.Privilege_1[i].Attributes);

}
}

}
class Tester
{
static void Main()
{
_PRIVILEGE_SET ps = new _PRIVILEGE_SET();

ps.PrivilegeCount = 2;
ps.Privilege_1 = new LUID_AND_ATTRIBUTES[2];
ps.Control = 2;
ps.Privilege_1[0].Luid.LowPart = 11;
ps.Privilege_1[0].Luid.HighPart = 122;
ps.Privilege_1[1].Luid.LowPart = 33;
ps.Privilege_1[1].Luid.HighPart = 444;
StructInspector.DisplayStruct(ps);
}
}
}

Willy.

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:eQ**************@tk2msftngp13.phx.gbl...
If you really want to use C# to pass such managed structures to
unmanaged code


But I did not say I wanted to do this! All I want is the ability to
declare and use a structure containing a directly embedded array, i.e. an
array whose data is part of the structure not outside it. There are
various
consequences, for example, copying the structure would necessarily copy
all
the array data as well. I only quoted the Win32 FIND_DATA and PRIVILEGE
SET
examples as evidence for my claim that such structures are not unsual.

I conclude that this simple and common requirement is not met in C#, and I
contend that this a defect of the language. Of course you can program
round
it in various clumsy ways, just as you can program round not using
structures at all.

Peter Seaman

Nov 15 '05 #31
Sorry, but your example does not achieve the embedded arrays desired. Run
your code with 3 statements added as shown below and note that the
assignment ps1 = ps does NOT copy the arrrays. Therefore your arrays are
OUTSIDE the structure and indirectly addressed, not INSIDE the structure and
directly addressed as I require and as would be the case in C or C++.

I want to treat a1 a2 a3 in the following structure as an array. I want the
array to be INSIDE the structure just like a1 a2 and a3 are. Then I can
treat the structure as a self-contained unit.

struct

{

int n;

int a1;

int a2;

int a3;

}

At this point I give up and am happy for you to have the last word.

Peter Seaman

----- Your code with 3 statements added -------

_PRIVILEGE_SET ps = new _PRIVILEGE_SET();

_PRIVILEGE_SET ps1 = new _PRIVILEGE_SET(); // New statement 1. ps1
is a separate strcuture.

ps.PrivilegeCount = 2;

ps.Privilege_1 = new LUID_AND_ATTRIBUTES[2];

ps.Control = 2;

ps.Privilege_1[0].Luid.LowPart = 11;

ps.Privilege_1[0].Luid.HighPart = 122;

ps.Privilege_1[1].Luid.LowPart = 33;

ps.Privilege_1[1].Luid.HighPart = 444;

ps1 = ps; // New
statement 2

ps1.Privilege_1[0].Luid.LowPart = 7; // new statement 3
StructInspector.DisplayStruct(ps); // note that
ps.Privilege_1[0].Luid.LowPart is now 7 not 11.
Nov 15 '05 #32

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:ue**************@tk2msftngp13.phx.gbl...
Sorry, but your example does not achieve the embedded arrays desired. Run
your code with 3 statements added as shown below and note that the
assignment ps1 = ps does NOT copy the arrrays.
*** As expected, it doesn't, it copies the variable ps1 holding a reference
(or address of) to the _PRIVILEGE_SET structure type to the variable ps , so
both ps and ps1 are now pointing to the same structure (the ps struct).
Accessing the fields using ps or ps1 will yield the same result.
But what has this to do whith embedded arrays in structs?

Therefore your arrays are OUTSIDE the structure and indirectly addressed, not INSIDE the structure
and
directly addressed as I require and as would be the case in C or C++.

*** You can't, simply because structures can be stack allocated and arrays
are allways GC heap allocated in .NET.
when declaring someStruct[] myStruct; in .NET you effectively say that
myStruct holds a reference (kind of opaque pointer type) to an array of type
someStruct allocated in the GC heap.
So the parent structure will contain a reference to a GC heap allocated
array, but you can threat the structure as a single entity and the array
access syntax used is the same as in C . The only difference is that the
array fields are on the heap, but why do you care where they are?
I want to treat a1 a2 a3 in the following structure as an array. I want
the
array to be INSIDE the structure just like a1 a2 and a3 are. Then I can
treat the structure as a self-contained unit.

struct

{

int n;

int a1;

int a2;

int a3;

}
*** Like this?

{
class Tester
{
static void Main()
{
A a = new A(3); // a is a reference to a struct of type A allocated on
the stack.
a.abc[0] = 1; // same syntax as C+C++ to access members
a.abc[1] = 2; // abc points to an array of ints on the heap, abc
is a struct field on the stack
a.abc[2] = 3;
Console.WriteLine("{0} {1} {2}",a.abc[0], a.abc[1], a.abc[2]);
}
}

struct A
{
internal int i;
internal int[] abc;
public A(int v) { // using a struct initializer
i = 0;
abc = new int[v]; // embedded reference abc, pointing to an array of
int's on the GC heap
}
}
}

Or ... without initializer....
static void Main()
{
A a; // struct a is allocated on the stack
a.abc = new int[3]; // abc is pointing to an array of ints on the
heap, abc is a reference fields on the stack
a.i = 123; // this value is on the stack
a.abc[0] = 1; // these values are on the heap.
a.abc[1] = 2;
a.abc[2] = 3;

}
}

struct A
{
internal int i; // struct (both fields) on the stack
internal int[] abc; // abc holds a reference to an array if int's
allocated on the heap
}
}

Here 'abc' defines an array of int's, but this could be an array of structs
as well. But again you should use classes, NEVER EVER use structs for this
UNLESS you have to interop with unmanaged code.
If you really can't live without C style structs, don't use C# or VB.NET and
stay with C/C++ or ME C++.
----------
At this point I give up and am happy for you to have the last word.
*** Thank you for the kind words.
Peter Seaman

----- Your code with 3 statements added -------

_PRIVILEGE_SET ps = new _PRIVILEGE_SET();

_PRIVILEGE_SET ps1 = new _PRIVILEGE_SET(); // New statement 1. ps1
is a separate strcuture.

ps.PrivilegeCount = 2;

ps.Privilege_1 = new LUID_AND_ATTRIBUTES[2];

ps.Control = 2;

ps.Privilege_1[0].Luid.LowPart = 11;

ps.Privilege_1[0].Luid.HighPart = 122;

ps.Privilege_1[1].Luid.LowPart = 33;

ps.Privilege_1[1].Luid.HighPart = 444;

ps1 = ps; // New
statement 2

ps1.Privilege_1[0].Luid.LowPart = 7; // new statement 3
StructInspector.DisplayStruct(ps); // note that
ps.Privilege_1[0].Luid.LowPart is now 7 not 11.


Quite normal, see above (or C# is not C/C++).
Willy.
Nov 15 '05 #33
Sorry, drop previous post, some more info and several errors corrected.

Willy.

"Willy Denoyette [MVP]" <wi*************@pandora.be> wrote in message
news:eW**************@TK2MSFTNGP11.phx.gbl...

"Peter Seaman" <Peter MS Seaman at StableSoftware.com> wrote in message
news:ue**************@tk2msftngp13.phx.gbl...
Sorry, but your example does not achieve the embedded arrays desired.
Run
your code with 3 statements added as shown below and note that the
assignment ps1 = ps does NOT copy the arrrays.


*** As expected, it doesn't copy the arrays, it copies all structure members
from ps to ps1, also the member "ps.Privilege_1" holding a reference (see
below) to the LUID_AND_ATTRIBUTES structure array to the "ps1.Privilege_1"
structure member, so
both ps.Privilege_1 and ps1.Privilege_1 are now pointing to the same
structure array (the LUID_AND_ATTRIBUTES struct).
Accessing the fields of the array struct using ps or ps1 will yield the
same result.
If you need to copy a struct you need to implement ICloneable::Clone, here's
a sample...

static void Main()
{
A a;
// A a = new A(3); // a on the stack
a.abc = new int[3]; // so is abc, pointing to an array on the heap
a.i = 123; // on the stack
a.abc[0] = 11;
a.abc[1] = 2;
a.abc[2] = 3;
A b = (A)a.Clone();
b.abc[0] = 7;
Console.WriteLine("{0} {1} {2}",a.abc[0], a.abc[1], a.abc[2]);
Console.WriteLine("{0} {1} {2}",b.abc[0], b.abc[1], b.abc[2]);

}
}

struct A : ICloneable
{
internal int i;
internal int[] abc;
public object Clone()
{
A obj = (A)this.MemberwiseClone();
obj.abc = new int[abc.Length];
return obj;

}
}

But again you shouldn't use struct for this in .NET, use should use classes,
also note that copy constructors don't exist in .NET and operator= semantics
are different from C/C++.
Therefore your arrays are OUTSIDE the structure and indirectly addressed, not INSIDE the structure
and
directly addressed as I require and as would be the case in C or C++.

*** You can't, simply because structures can be stack allocated and arrays
are allways GC heap allocated in .NET.
when declaring someStruct[] myStruct; in .NET you effectively say that
myStruct holds a reference (kind of opaque pointer type) to an array of type
someStruct allocated in the GC heap.
So the parent structure will contain a reference to a GC heap allocated
array, but you can threat the structure as a single entity and the array
access syntax used is the same as in C . The only difference is that the
array fields are on the heap, but why do you care where they are?
I want to treat a1 a2 a3 in the following structure as an array. I want
the
array to be INSIDE the structure just like a1 a2 and a3 are. Then I can
treat the structure as a self-contained unit.

struct

{

int n;

int a1;

int a2;

int a3;

}
*** Like this?

{
class Tester
{
static void Main()
{
A a = new A(3); // a is a struct of type A allocated on
the stack.
a.abc[0] = 1; // same syntax as C+C++ to access members
a.abc[1] = 2; // abc points to an array of ints on the heap, abc
is a struct field on the stack
a.abc[2] = 3;
Console.WriteLine("{0} {1} {2}",a.abc[0], a.abc[1], a.abc[2]);
}
}

struct A
{
internal int i;
internal int[] abc;
public A(int v) { // using a struct initializer
i = 0;
abc = new int[v]; // embedded reference abc, pointing to an array of
int's on the GC heap
}
}
}
.... or sample above....

Here 'abc' defines an array of int's, but this could be an array of structs
as well. But again you should use classes, NEVER EVER use structs for this
UNLESS you have to interop with unmanaged code.
If you really can't live without C style structs, don't use C# or VB.NET and
stay with C/C++ or ME C++.

----------
At this point I give up and am happy for you to have the last word.
*** Thank you for the kind words.
Peter Seaman

----- Your code with 3 statements added -------

_PRIVILEGE_SET ps = new _PRIVILEGE_SET();

_PRIVILEGE_SET ps1 = new _PRIVILEGE_SET(); // New statement 1. ps1
is a separate strcuture.

ps.PrivilegeCount = 2;

ps.Privilege_1 = new LUID_AND_ATTRIBUTES[2];

ps.Control = 2;

ps.Privilege_1[0].Luid.LowPart = 11;

ps.Privilege_1[0].Luid.HighPart = 122;

ps.Privilege_1[1].Luid.LowPart = 33;

ps.Privilege_1[1].Luid.HighPart = 444;

ps1 = ps; // New
statement 2

ps1.Privilege_1[0].Luid.LowPart = 7; // new statement 3
StructInspector.DisplayStruct(ps); // note that
ps.Privilege_1[0].Luid.LowPart is now 7 not 11.


Quite normal, see above (or C# is not C/C++).
Willy.

Nov 15 '05 #34

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
4831
by: Java script Dude | last post by:
Some programmers prefer to stay with native level data structures such as string arrays instead of using Object based data structures such as ArrayList. From and efficiency point of view. Are...
7
2443
by: Squignibbler | last post by:
Hi all, I have a question regarding the C++ programming language regarding the nature of the relationship between pointers and arrays. If the statement MyArray is functionally identical to...
1
1450
by: ORC | last post by:
Hi, I have posted almost the same message in the compact framework group, but it seems to got lost in a deep message structure :-) so I'll try again: I'll receive a byte array from a serial...
2
1811
by: Andrew Burlak | last post by:
Hi, Although Unsized Arrays inside structures is a non-standard feature, I like to use it :-) It seems that Unsized Arrays are broken when /Og (Global Optimization) is enabled. The problem...
1
2513
by: Raj | last post by:
Hi, This is regarding using Arrays of UDT's in COM. The following is a short description: - We basically need a structure, struct MAIN_STRUCT which must contain a dynamic array of another...
1
1396
by: John Dann | last post by:
Is it possible in VB.net to have arrays of structures (ie UDTs) where the structure definition includes one or more arrays? Something like: Structure MyUDT ItemOne () as byte 'for example sub...
10
4968
by: David Fort | last post by:
Hi, I'm upgrading a VB6 app to VB.net and I'm having a problem with a call to a function provided in a DLL. The function takes the address of a structure which it will fill in with values. I...
0
1344
by: Art Cummings | last post by:
Good morning all. I just finished an assignment using structures. In this assignment I used an array of structures. What I would have liked was to use an array of structures with a function. ...
127
4750
by: sanjay.vasudevan | last post by:
Why are the following declarations invalid in C? int f(); int f(); It would be great if anyone could also explain the design decision for such a language restricton. Regards, Sanjay
0
7133
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7336
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7405
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
5059
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4724
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3214
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3198
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1568
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
435
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.