Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ VB.NET
Hi,
 
I am quite new to C++.Could anyone tell me how to copy structure to another structure (binary)?
 
structure looks like this:
typedef unsigned char DES_cblock[8];
#ifndef DES_LONG
#define DES_LONG unsigned long
#endif
 
typedef struct DES_ks
    {
    union
    {
    DES_cblock cblock;
    /* make sure things are correct size on machines with
     * 8 byte longs */
    DES_LONG deslong[2];
    } ks[16];
    } DES_key_schedule;
 
declaration in class:
  DES_key_schedule ks1;
  DES_key_schedule ks2;
 
Now I need to copy both structure to another structure which is later passed to VB.net (unmanaged code).
 
Using simple method assignem works but returns an error 'System.ExecutionEngineException' in vb:
void cWrapper::ScheduleKeyRun(myStruct *cd)
{
    memcpy(desKey , cd->desKey, 16);
    //do things
    int sz = sizeof(DES_key_schedule);
    DES_key_schedule mks1=cd->ks1;
    cd->ks1 = ks1;
    cd->ks2 = ks2;
}
 
Could anyone check tell me if transfared structure corectly to VB.NET
<StructLayout(LayoutKind.Sequential)> _
Structure DES_key_schedule
    Dim block As DES_cblock
    <MarshalAs(UnmanagedType.I2)> Dim dlong As Short
End Structure
<StructLayout(LayoutKind.Sequential)> _
Structure DES_cblock
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> Dim cblock() As Byte
End Structure
or in c# would be:
[StructLayout(LayoutKind.Sequential)]
struct DES_key_schedule
{
    public DES_cblock block;
    [MarshalAs(UnmanagedType.I2)]
    public short dlong;
}
[StructLayout(LayoutKind.Sequential)]
struct DES_cblock
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] cblock;
}
Posted 10-Jan-12 11:45am
Edited 11-Jan-12 0:24am
v3
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

With a structure, you can just do a memory copy.
Be aware that both structures must have the same layout.
    memcpy(&cd->ks1, &ks1, sizeof(cd->ks1));
    memcpy(&cd->ks2, &ks2, sizeof(cd->ks2));
 

If you're not happy with the memcpy, you can do something slightly more complicated.
typedef struct DES_ks
{
    union
    {
        DES_cblock cblock;
        /* make sure things are correct size on machines with
         * 8 byte longs */
        DES_LONG deslong[2];
    }   ks[16];
 

public:
    const DES_ks & operator = (const DES_ks & rhs);
 
public:
    DES_ks(void)    { /* your choice to put in initialization 
                         The original struct didn't have it.*/ }
    DES_ks(const DES_ks & rhs);
 
} DES_key_schedule;
 
inline const DES_ks & DES_ks::operator = (const DES_ks & rhs)
{
    for (size_t Index = 0; Index < (sizeof(ks) / sizeof(ks[0])); Index++)
    {
        ks[Index].deslong[0] = rhs.ks[Index].deslong[0];
        ks[Index].deslong[1] = rhs.ks[Index].deslong[1];
    }
 
    return *this;
}
 
inline DES_ks::DES_ks(const DES_ks & rhs)
{
    *this = rhs;
}
 
With the operator overloading you can use:
    cd->ks1 = ks1;
    cd->ks2 = ks2;
  Permalink  
v9
Comments
Stefan_Lang at 11-Jan-12 4:06am
   
I don't consider that good advice, since mem functions should generally be avoided in C++. In fact, it will fail when one of the struct members is a compound C++ type that normally requires a call to a (copy-) constructor to be initialized corectly - one obvious example would be std::string.
 
Besides, it isn't even necessary since that is what compiler already does if you don't define a copy constructor for the struct yourself: you can just assign one struct to the other to get exactly the same (potentially faulty) result.
Tomazas77 at 11-Jan-12 4:46am
   
Stefan, could you check if I transfered C++ structure corectly to .NET (see edited question)? Or this relates to KB327106?
Stefan_Lang at 11-Jan-12 5:36am
   
Sorry, can't help with marshalling. I made this comment only because memcpy doesn't care about memory layout, and therefore is likely to mess up your structure. (and I strongly suspect that marshalling does change the memory layout!)
 
The only advice I can offer is writing a function to copy one struct to the other, field by field. The difficulty I see however is that I have no idea how to marshal a union, or if it is even possible. I suspect that is your actual problem.
Tomazas77 at 11-Jan-12 5:42am
   
I found some article regarding the struct union in C++ where it says that struct with unions can be only pointers. Now I've tried to pass just this structure to C++ and I can see invalid pointers in this structure, so I guess that my structure is not right for vb.net.
JackDingler at 11-Jan-12 9:31am
   
You can put any basic C data type you want, in a union.
you can even include structs with their own unions.
 
The issue is that the default C++ copy mechanism isn't going to work correctly with these simple C data types.
 
The standard C way of doing it is with a memcpy().
I've posted a C++ solution as an update, with a deep copy.
 
You may also need the following around your structure...
 
#pragma pack(push, 1)
struct MyStruct
{
...
};
#pragma pack(pop)
 
This ensures that the structure doesn't contain any padding. This is a standard layout for structs passed to APIs. Unless the API defines the padding differently.
JackDingler at 11-Jan-12 9:15am
   
When both structures are the same, and doesn't contain complex types, it will not mess up your memory layout.
 
In the example of above, 'what you argue is likely', is actually impossible.
 
The layout is strongly typed by the union, and the data types.
I updated my solution to show it with marshaling.
 
The structure is just an array of unsigned longs.
JackDingler at 11-Jan-12 8:58am
   
There a definite gotchas to using memcpy().
 
And of course there are times when you need a deep copy instead of shallow copy.
 
But that isn't the case here. He has standard C types in the structure.
 
In the case of the char arrays, the default copy is not going to do the trick.
Stefan_Lang at 11-Jan-12 9:53am
   
The OP didn't originally provide the types for DES_cblock and DES_long, so there was no way to know if it was safe or not.
 
I don't see why the default copy wouldn't handle the char arrays properly? They're flat storage just as the longs. AFAIK default copy does the same as memcpy. Can't seem to remember a reference though...
 
That said, I don't think the problem is in any way related to that: IMHO the C# (and VB.NET) declarations are wrong.
JackDingler at 11-Jan-12 10:27am
   
But how does C++ handle the union? Does it copy the character array or the unsigned longs?
JackDingler at 11-Jan-12 10:32am
   
Just tried it. It works fine.
Stefan_Lang at 11-Jan-12 10:41am
   
For all I know it may even call memcpy itself :o)
Tomazas77 at 11-Jan-12 4:32am
   
Looks like it copies the data but this returns an error in .NET interface:
"An unhandled exception of type 'System.ExecutionEngineException' occurred in Application1.exe"
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

This is just an educated guess, since I'm not familiar with marshalling, but this:
[StructLayout(LayoutKind.Sequential)]
struct DES_key_schedule
{
    public DES_cblock block;
    [MarshalAs(UnmanagedType.I2)]
    public short dlong;
}
...looks like a struct with two members to me, and that is not what you declared in C++.
 
After consulting http://msdn.microsoft.com/de-de/library/system.runtime.interopservices.layoutkind.aspx[^] I would assume a definition of a union should look like that:
[StructLayout(LayoutKind.Explicit)]
struct DES_key_schedule
{
    [FieldOffset(0)] public DES_cblock block;
    [FieldOffset(0)] public int dlong[2];
}
  Permalink  
Comments
Tomazas77 at 11-Jan-12 10:37am
   
I've tried to replicate the structure but I couldn't. It's just too complex and event quit good explanation link did not helped me. All structures was in C++ with invalid pointers.
 
Then I've tried just to copy all structure to binary array (the size I know - its 128) and this did not returned errors. That just worked! Its just bytes.
I may think that your proposed structure may work. I'll try this out later.
 
Thanks
Tomazas77 at 11-Jan-12 11:05am
   
Any tries to compile project with initialisation of structure fails over with error:
"Could not load type 'WindowsApplication1.NewCamD.DES_ks' from assembly 'NewCamDLibrary_test.NET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field."
 
Your structure missing another array of 16 values. Structure should be something like
<structlayout(layoutkind.explicit)> _
Structure DES_key_schedule
<fieldoffset(0),MarshalAs(UnmanagedType.ByValArray, SizeConst:=16)> Dim ks() As DES_ks
Sub New(ByVal val As Boolean)
ReDim ks(16)
For j As Integer = 0 To 15
ks(j) = New DES_ks(True)
Next
End Sub
End Structure
 
<structlayout(layoutkind.explicit)> _
Structure DES_ks
<fieldoffset(0),MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> Dim cblock() As Byte
<fieldoffset(0)> Dim dlong As UInt32
Sub New(ByVal val As Boolean)
ReDim cblock(8)
End Sub
End Structure
Stefan_Lang at 12-Jan-12 3:56am
   
Sorry, I'm giving up at this point - this is a C#/VB.NET problem, not C++, and there is no point for me to look into the documentation and make further educated guesses. Since your posting is already tagged as VB.NET and didn't get it to work so far, I suggest you either add the tag C# as well, or repost on the .NET discussion forum, with a link to this Q&A.
 
P.S.: It may be a good idea to reformulate the topic: at this point it seems pretty clear to me that the problem is marshalling a struct to C# or VB, not the copying of the struct in C++.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

After lots of testing I decided to try to pass binary array for storing (I need only this for reuse only). Using memcpy function this worked!
 
Tried other solutions, but VB.NET does not let me compile the project with zero field ofsets in structure. In other cases modifying structure did not worked in C++ (was corrupting memory) because I guess this is too complex, so I am staying with my solution.
 
Thanks for help
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

I donot think you can do this - cd->ks1 = ks1; Because the ks1 is a local variable and created on stack. Create struct in heap, using new operator, then give a try.
  Permalink  
Comments
JackDingler at 11-Jan-12 9:17am
   
Whether it's on the heap or stack doesn't matter.
Kethu Sasikanth at 12-Jan-12 13:10pm
   
i'm sorry not being clear on my answer, cd->ks1 =ks1; you cannot do this because it is going to cross into another boundary (may be a thread or process) so better new(create in heap) it or do = operator overload to assign the values.
JackDingler at 12-Jan-12 13:34pm
   
It doesn't matter in C/C++. It's all the same memory space.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 DamithSL 270
1 OriginalGriff 184
2 BillWoodruff 170
3 Zoltán Zörgő 165
4 Sergey Alexandrovich Kryukov 125
0 OriginalGriff 7,760
1 DamithSL 5,874
2 Sergey Alexandrovich Kryukov 5,444
3 Maciej Los 5,076
4 Kornfeld Eliyahu Peter 4,539


Advertise | Privacy | Mobile
Web01 | 2.8.141223.1 | Last Updated 12 Jan 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100