CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Feb 2006
    Posts
    6

    Question How to create sizeable struct in C#?

    In C++, I have a struct like that:

    struct SocketData{
    int cbsize;
    char name[20];
    int cmd[3];
    char data[1];
    };

    It means that I can create a sizeable struct but all member datas are stored in continuous memory.
    In C#, I know that array is defined as reference so I don't know how to create sizeable struct in C#.

  2. #2
    Join Date
    Mar 2004
    Location
    Prague, Czech Republic, EU
    Posts
    1,701

    Re: How to create sizeable struct in C#?

    In managed code, you have no control over memory and it is right so. You hasn't take care about it. Your demand makes sence only if you would like to pass your struct to unmanaged code (e.g. in P/Invoke). Then you can use StructLayoutAttribute and set it to sequential. See example.

    Code:
    [StructLayout(LayoutKind.Sequential)]
    struct SocketData{
    int cbsize;
    char name[20];
    int cmd[3];
    char data[1];
    };
    • Make it run.
    • Make it right.
    • Make it fast.

    Don't hesitate to rate my post.

  3. #3
    Join Date
    Feb 2006
    Posts
    6

    Re: How to create sizeable struct in C#?

    I think the reason is:

    Code:
    [StructLayout(LayoutKind.Sequential)]
    public struct SocketData
    {
    	public int cbsize;
    	public char[] name;
    	public int[] cmd;
    	public char[] data;
    }
    
    public class Test
    {
    	void Main()
    	{
    		SocketData sockData = new 	SocketData();
    		sockData.cbsize = 100;
    		sockData.name = new char(20);
    		sockData.cmd = new int(3);
    		sockData.data = new int(73); // 100 - 4 - 20 - 3 = 73
    	}
    }
    Because the struct contains array members that will be allocated after object declared so that they are all references and not sequential.

  4. #4
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: How to create sizeable struct in C#?

    sorry I havent gotten back to your email (I'm just now sitting down to it & noticed you posted here).

    you can define size constants in your struct:

    Code:
    struct SocketData {
        public int cbsize;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
        public char[] name;
        public int cmd;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public char[] data;
    }
    then you should be able to marshal it as I did in the original thread you were asking about.

    you can also mark the struct as explicit in the structlayout attribute (instead of sequential), and explicitly define how members will be laid out. I dont think that helps your situation though.

    you said your struct will be sizable (I'm assuming by the 2 arrays you have there)? in my example (in the other thread) I allocated a buffer using the sizeof the struct (because the size was constant), but if you know how large you're going to allocate the 2 members, then you should be able to define the size of buffer you'll marshal the struct to, then do it exactly the same as before (once you pin the data in memory using gchandle you shouldnt have any problems marshaling it). I havent tried it so I could be wrong, but it sounds like this should work.

    good luck... again, sorry I havent been of much help.

  5. #5
    Join Date
    Feb 2006
    Posts
    6

    Re: How to create sizeable struct in C#?

    Here is a sample of sizeable struct that I used.

    Code:
    #include <stdio.h>
    #include <memory.h>
    
    struct SocketData{
    	int cbsize;
    	char name[20];
    	int cmd[3];
    	char data[1];
    };
    
    void main()
    {
    
    	int x[] = {1, 2, 3, 4, 5};
    	char str[] = "Hello, world";
    
    	SocketData* lpSockData;
    	int size;
    
    
    	//1. The first allocated
    	size = sizeof(SocketData) + sizeof(x);
    	lpSockData = (SocketData *) new char[size];
    
    	lpSockData->cbsize = size;
    	memcpy(lpSockData->data, (char*) x, sizeof(x));
    	delete lpSockData;
    
    	//2. The second allocated
    	size = sizeof(SocketData) + sizeof(str);
    	lpSockData = (SocketData *) new char[size];
    
    	lpSockData->cbsize = size;
    	memcpy(lpSockData->data, (char*) str, sizeof(str));
    	delete lpSockData;
    }
    It is difficult for me to do so in C#.

  6. #6
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: How to create sizeable struct in C#?

    perhaps you can use the binary formatter & just serialize the struct:

    Code:
    [Serializable]
    struct SocketData {
        public int cbsize;
        public char[] name;
        public int cmd;
        public char[] data;
    }
    and the formatting code:
    Code:
    SocketData sd = new SocketData();
    sd.name = new char[] {'t','e','s','t'};
    sd.data = new char[] {'h','e','l','l','o',' ','w','o','r','d'};
    sd.cmd = 12;
    sd.cbsize = sd.data.Length;
    byte[] buffer = null;
    BinaryFormatter bf = new BinaryFormatter();
    
    // encode the data into a byte array so you can send it
    using(MemoryStream ms = new MemoryStream()) {
        bf.Serialize(ms, sd);
        buffer = ms.ToArray();
    }
    
    // send & recieve data over the socket
    byte[] recieved = new byte[buffer.Length];
    Array.Copy(buffer, recieved, buffer.Length);
    
    // read in the byte array and deserialize it to SocketData
    using(MemoryStream ms = new MemoryStream()) {
        ms.Write(buffer, 0, buffer.Length);
        ms.Seek(0, 0);
        SocketData data = (SocketData)bf.Deserialize(ms);
    }
    I dont know if you have to communicate w/ the older system which copy's the struct from memory, in which case this isnt going to work for you. but if you're writing both ends in C# then you should be fine.

  7. #7
    Join Date
    Feb 2006
    Posts
    6

    Re: How to create sizeable struct in C#?

    Quote Originally Posted by MadHatter
    perhaps you can use the binary formatter & just serialize the struct:

    Code:
    [Serializable]
    struct SocketData {
        public int cbsize;
        public char[] name;
        public int cmd;
        public char[] data;
    }
    and the formatting code:
    Code:
    SocketData sd = new SocketData();
    sd.name = new char[] {'t','e','s','t'};
    sd.data = new char[] {'h','e','l','l','o',' ','w','o','r','d'};
    sd.cmd = 12;
    sd.cbsize = sd.data.Length;
    byte[] buffer = null;
    BinaryFormatter bf = new BinaryFormatter();
    
    // encode the data into a byte array so you can send it
    using(MemoryStream ms = new MemoryStream()) {
        bf.Serialize(ms, sd);
        buffer = ms.ToArray();
    }
    
    // send & recieve data over the socket
    byte[] recieved = new byte[buffer.Length];
    Array.Copy(buffer, recieved, buffer.Length);
    
    // read in the byte array and deserialize it to SocketData
    using(MemoryStream ms = new MemoryStream()) {
        ms.Write(buffer, 0, buffer.Length);
        ms.Seek(0, 0);
        SocketData data = (SocketData)bf.Deserialize(ms);
    }
    I dont know if you have to communicate w/ the older system which copy's the struct from memory, in which case this isnt going to work for you. but if you're writing both ends in C# then you should be fine.
    I think it is quite good.
    Thank you very much.

  8. #8
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: How to create sizeable struct in C#?

    The supposedly C++ code that you showed is not C++ not even correct C. main is int main() and not void main(). Ignoring these, even then you cannot be sure that the allocation is totally contiguous. Recall, structure alignment issue. If it is the arrays that you are worried about - if they would acquire contiguous allocations - be sure - they will. Regards.

  9. #9
    Join Date
    Feb 2006
    Posts
    6

    Re: How to create sizeable struct in C#?

    That code I have written in VC++. I have checked memory address of all variable members of struct, it is contiguous. It may be not right in other C/C++ compilers.
    Thank you for your advice.

  10. #10
    Join Date
    Feb 2006
    Posts
    6

    Re: How to create sizeable struct in C#?

    I go with MadHatter suggestion and I found that the length of the buffer serialized is quite bigger than real length of the struct. C# have a header for data serialized. If there is a way to solve it, reduce the length of buffer serialized?

  11. #11
    Join Date
    Dec 2005
    Posts
    282

    Re: How to create sizeable struct in C#?

    Search for Unmanaged code Calls...There are a lot of description...

    May be you can find something in the links below:

    http://www.dotnet247.com/247reference/msgs/4/21576.aspx
    http://www.csharphelp.com/archives/archive52.html
    http://www.codeproject.com/csharp/ObjectPooling.asp


    Regards
    Hansjörg

  12. #12
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: How to create sizeable struct in C#?

    using a binary formatter, the framework stores some extra info about the object (like info about the assembly which serilized it).

    the problem is that the framework doesnt include a way to get size of a struct which doesnt explicitly layout its offsets (or have them implied using a sequential layout). I dont know of any way to define offsets with an instance of an object (which is what you'd need to do to marshal it using the built in MarshalStructureToPtr.

    you may want to search for marshaling sized objects at runtime, and see if there are any examples out there (I'm sure there are if its possible).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured