memcpy char* in C#

D

DatelMonkey99

I have some c++ code that I am converting to C#. What I need to convert is
the following:

memcpy(&tmpshort, (pTmpDataIn+1), 2);

This should copy two bytes of an char* to an int which then gets used
elsewhere. I am having trouble coming up with how to approach.

Thanks,

~ Steve
 
P

Peter Duniho

I have some c++ code that I am converting to C#. What I need to convert
is
the following:

memcpy(&tmpshort, (pTmpDataIn+1), 2);

This should copy two bytes of an char* to an int which then gets used
elsewhere. I am having trouble coming up with how to approach.

To an int? Or a short?

Maybe something like this:

short tmpshort = BitConverter.ToInt16(pTmpDataIn, 1);

where "pTmpDataIn" is type "byte[]".

Note that in C#, a character array isn't the same as a byte array. If you
don't already have something that is an actual array of bytes or from
which you can get an actual array of bytes, you'll need to be more
specific about your question.

Pete
 
A

Arne Vajhøj

DatelMonkey99 said:
I have some c++ code that I am converting to C#. What I need to convert is
the following:

memcpy(&tmpshort, (pTmpDataIn+1), 2);

This should copy two bytes of an char* to an int which then gets used
elsewhere. I am having trouble coming up with how to approach.

I am not even sure that I understand why memcpy was used in C.

tmpshort = (short)((pTmpDataIn[2] << 8) | pTmpDataIn[1]);

Arne
 
W

Walter Wang [MSFT]

Hi Steve,

This will depend on how you're converting the "char *" from C to C#: if you
are using a String, then you can get a char array using string.ToCharArray
and add up two chars yourself, just remember a char in C# is a unicode. In
this case, the unmanaged memory will be marshalled to managed string
automatically if you are using P/Invoke function calls and do it correctly.

If you are using an IntPtr in C# to access the unmanaged memory, then you
can use Marshal.ReadInt16, Marshal.ReadInt32, etc. to read the unmanaged
memory.

Hope this helps.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
D

DatelMonkey99

Thank you all for the responses, sorry for not being more clear in my
question.

I am doing some socket programming where I listen on a port then reconstruct
some data from the message. Here is what I am doing in C#.

//Get the message from the socket
int iRx = socketData.m_currentSocket.EndReceive(asyn);

//convert to char[]
char[] chars = new char[iRx + 1];

// Extract the characters as a buffer
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);

This works to a point. However some pieces are not matching that I see in
the c++ source.

The c++ source has some enums setup that give message state. On receive it
first determines the message type & then gets the data from the message.
Here is that code in c++.

//Get message type (SessionMessageId is the enum / pMessageIn in the
unsigned char *)
msgID = (SessionMessageId)*pMessageIn;

//Copy the next two bytes to get the size of the message
memcpy(&tmpshort, (pTmpDataIn+1), 2);
length = ntohs(tmpshort);

I've worked through the posts from Peter & Arne but am still not being able
to get the correct data out of the message.

Thanks,

~ Stev
 
A

Arne Vajhøj

DatelMonkey99 said:
I am doing some socket programming where I listen on a port then reconstruct
some data from the message.


Have you looked at the System.IO.BinaryReader class ?

If your C++ app send in little endian then it should
be very easy to read the data with a BinaryReader !

Arne
 
P

Peter Duniho

[...]
The c++ source has some enums setup that give message state. On receive
it
first determines the message type & then gets the data from the message.
Here is that code in c++.

//Get message type (SessionMessageId is the enum / pMessageIn in the
unsigned char *)
msgID = (SessionMessageId)*pMessageIn;

//Copy the next two bytes to get the size of the message
memcpy(&tmpshort, (pTmpDataIn+1), 2);
length = ntohs(tmpshort);

What C# code have you tried?

It's worth noting that while you can use the Encoder class to convert
bytes sent to characters, those characters are not going to be useful
later for getting non-character data, such as the length. You'll need to
use the receive buffer (socketData.dataBuffer) directly with the
BitConverter.

Whether this is the issue you're having trouble with, I don't know. You
need to post code for us to know what you're trying and offer advice as to
how to do it better.

Pete
 
B

Ben Voigt [C++ MVP]

Arne Vajhøj said:
DatelMonkey99 said:
I have some c++ code that I am converting to C#. What I need to convert
is the following:

memcpy(&tmpshort, (pTmpDataIn+1), 2); This should copy two bytes of an
char* to an int which then gets used elsewhere. I am having trouble
coming up with how to approach.

I am not even sure that I understand why memcpy was used in C.

tmpshort = (short)((pTmpDataIn[2] << 8) | pTmpDataIn[1]);

There's a potential endianness difference here. memcpy is guaranteed to
work with the local processor endianness in the buffer, while yours is
guaranteed to need LSB-first. Also you need some unsigned casts in that
expression to prevent sign-extension of the LSB from overwriting the MSB.
 
P

Peter Duniho

I am not even sure that I understand why memcpy was used in C.

tmpshort = (short)((pTmpDataIn[2] << 8) | pTmpDataIn[1]);

There's a potential endianness difference here. memcpy is guaranteed to
work with the local processor endianness in the buffer,

Assuming the data was originally the same endianness as that being used.
That wouldn't be guaranteed if, for example, the data was previously
stored in a file or transmitted over a network or...

So let's assume that we can guarantee the endianness is always the same
and let's assume the reason is that the origin of the data is internal to
the application (I know, that's a lot of assumptions :) ). Then...
while yours is guaranteed to need LSB-first.

Does .NET run on any big-endian systems? If the data originates from
within the application, are there true .NET scenarios where code that
assumes little-endian wouldn't work?

Until Mono has 100% parity with .NET (which I assume will never
happen...another assumption, I know :) ), I wouldn't consider it a
legitimate concern, even if it does run on a big-endian system (being
open-source, I assume it eventually will even if it doesn't now...does
Mono work on PowerPC-based Macs?)
Also you need some unsigned casts in that
expression to prevent sign-extension of the LSB from overwriting the MSB.

Or just masking would work too.

That said, in C something as simple as "tmpshort = *((short *)(pTmpDataIn
+ 1));" should have worked fine. There wasn't really a need to call
memcpy _or_ to manipulate the individual bytes of the original data.

If we're going to deconstruct the original C, we might as well do a
complete job. :)

Pete
 
A

Arne Vajhøj

Ben said:
Arne Vajhøj said:
DatelMonkey99 said:
I have some c++ code that I am converting to C#. What I need to convert
is the following:

memcpy(&tmpshort, (pTmpDataIn+1), 2); This should copy two bytes of an
char* to an int which then gets used elsewhere. I am having trouble
coming up with how to approach.
I am not even sure that I understand why memcpy was used in C.

tmpshort = (short)((pTmpDataIn[2] << 8) | pTmpDataIn[1]);

There's a potential endianness difference here. memcpy is guaranteed to
work with the local processor endianness in the buffer, while yours is
guaranteed to need LSB-first.

I am guessing at x86 architecture ...

:)
Also you need some unsigned casts in that
expression to prevent sign-extension of the LSB from overwriting the MSB.

bytes are unsigned in C#, so I assume that is OK as is.

Arne
 
A

Arne Vajhøj

Peter said:
On Mon, 31 Dec 2007 12:19:53 -0800, Ben Voigt [C++ MVP]
Does .NET run on any big-endian systems? If the data originates from
within the application, are there true .NET scenarios where code that
assumes little-endian wouldn't work?

Until Mono has 100% parity with .NET (which I assume will never
happen...another assumption, I know :) ), I wouldn't consider it a
legitimate concern, even if it does run on a big-endian system (being
open-source, I assume it eventually will even if it doesn't now...does
Mono work on PowerPC-based Macs?)

Mono runs at MacOS X/PPC, Solaris SPARC, Linux/PPC and
Linux/IBM mainframe.

But I am sure that Linux/x86 is by far the most used
platform for Mono.

I do recall reading about a Mono on MacOS X problem, so it is
used. The other I have never heard about.
Or just masking would work too.

For byte which is unsigned ??
That said, in C something as simple as "tmpshort = *((short
*)(pTmpDataIn + 1));" should have worked fine. There wasn't really a
need to call memcpy _or_ to manipulate the individual bytes of the
original data.

Don't post that to comp.lang.c - some language lawyer will tell
you that it is undefined or implementation specific behavior (*).

Arne

*) On a few CPU architectures you will get a segmentation fault if
the address pTmpDataIn + 1 is not a multipla of sizeof(short).
The few includes SPARC.
 
J

Jesse McGrew

I am not even sure that I understand why memcpy was used in C.
tmpshort = (short)((pTmpDataIn[2] << 8) | pTmpDataIn[1]);
There's a potential endianness difference here. memcpy is guaranteed to
work with the local processor endianness in the buffer,

Assuming the data was originally the same endianness as that being used.
That wouldn't be guaranteed if, for example, the data was previously
stored in a file or transmitted over a network or...

So let's assume that we can guarantee the endianness is always the same
and let's assume the reason is that the origin of the data is internal to
the application (I know, that's a lot of assumptions :) ). Then...
while yours is guaranteed to need LSB-first.

Does .NET run on any big-endian systems? If the data originates from
within the application, are there true .NET scenarios where code that
assumes little-endian wouldn't work?

..NET can run on the Xbox 360 (via XNA), which is a PowerPC platform.

Jesse
 
W

Walter Wang [MSFT]

Hi Steve,

To translate the C code, I think you can basically use following steps:

1) Read in two bytes
2) Use BitConverter to convert the two bytes into Int16
3) Use IPAddress.NetworkToHostOrder to convert the data from network byte
order to host byte order

Reference:

#CodeGuru: Receiving & Converting Numeric and String Data via Sockets
http://www.codeguru.com/cpp/cpp/algorithms/strings/article.php/c6839/


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top