Click here to Skip to main content
15,891,372 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I am quite new to C++.Could anyone tell me how to copy structure to another structure (binary)?

structure looks like this:
C++
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:
C++
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:
C++
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
VB
<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:
C#
[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
Updated 10-Jan-12 23:24pm
v3
Comments
Zarif Bahadori 14-Apr-21 20:25pm    
Write a program to copy one structure to another structure .(using pointer)

With a structure, you can just do a memory copy.
Be aware that both structures must have the same layout.
C++
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.
C++
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:
C++
cd->ks1 = ks1;
cd->ks2 = ks2;
 
Share this answer
 
v9
Comments
Stefan_Lang 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 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 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 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 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.
This is just an educated guess, since I'm not familiar with marshalling, but this:
C++
[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:
C#
[StructLayout(LayoutKind.Explicit)]
struct DES_key_schedule
{
    [FieldOffset(0)] public DES_cblock block;
    [FieldOffset(0)] public int dlong[2];
}
 
Share this answer
 
Comments
Tomazas77 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 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 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++.
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
 
Share this answer
 
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.
 
Share this answer
 
Comments
JackDingler 11-Jan-12 9:17am    
Whether it's on the heap or stack doesn't matter.
Kethu Sasikanth 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 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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900