Little Problem

  • Thread starter Angel J. Hernández M
  • Start date
A

Angel J. Hernández M

Hi folks! I'm having a little problem and I'm a bit confused about it.
See... I'm working on this VoIP project (I need to use make direct calls to
Windows API). I started working using C# but since I've got to access the
API constantly I'd rather write all low-level stuff in C++ and create the UI
using C#. So far so good... I created a sniffer socket (in order to
determine if it's H.323 compliant). This routine was written firstly in C#
but since I want to have all low level stuff in C++ I ported it to. Ok... My
problem is the next...

I have somthing like this (This code works OK)...

protected virtual unsafe object[] ParseIPHeader(byte[] packet, int
length) {
short src_port = 0, dst_port = 0;
object[] retval = new object[6];

fixed(byte* packetdata = packet) {
CCommon.IPHeader* ipheader = (CCommon.IPHeader*) packetdata;
// Rest of code goes here...
}

Here IPHeader is a struct I use to store IP packet's header... Then I have
the new C++ code...

Object* CRawSocket::parseIPHeader(Byte packet[], int length)[] {
short src_port = 0, dst_port = 0;
System::Text::StringBuilder *src_address, *dst_address;
Object *retval[] = new Object*[6];
src_address = new System::Text::StringBuilder();
dst_address = new System::Text::StringBuilder();

Byte *packeddata = __try_cast< Byte *>(&packet[0]) ;
CCommon::IPHeader *ipheader = (CCommon::IPHeader *) &packeddata;
// Rest of code goes here...
}

My problem is that I don't get the same results even though it's almost the
same code :s

As we all know in C# we pass "addresses" so there's no need to write

fixed(byte* packetdata = &packet) // wrong!

but in the C++ world I need to pass the address

I've tried this...

Byte* packeddata = packet; // I get error C2440: 'initializing' : cannot
convert from 'unsigned char __gc[]' to 'unsigned char __gc *'
Byte *packeddata = __try_cast< Byte *>(&packet[0]); // This compiles OK
but it doesn't get the address I need :but the char value instead :s

I need some help with this... Any Ideas?

Thanks in advance


Byte *packeddata = __try_cast< Byte *>(&packet[0]) ;
 
B

Ben Schwehn

fixed(byte* packetdata = &packet) // wrong!

but in the C++ world I need to pass the address

I've tried this...

I'm not entirly sure what you're trying to do but instead of c#'s fixed
what you'll probably want to do is use __pin something like

int __pin* p = &packet[0];

to get the address of packet and also pin the entire array

hth
 
A

Angel J. Hernández M

Hi there... That's not the problem...

I've got a code written in C# and works fine but I call a lot of API
functions so I decided to write the low-level stuff in C++. My problem is
(not about __pin cuz I already try that). I have a struct which is
responsible for storing packet's IP Header. It's defined like this...

[StructLayout(LayoutKind::Explicit)]
__value struct IPHeader {
[FieldOffset(0)] Byte verlen; // IP Version & IP Header
length
[FieldOffset(1)] Byte tos; // Type of service
[FieldOffset(2)] UInt16 length; // Packet's total length
[FieldOffset(4)] UInt16 id; // Unique identifier
[FieldOffset(6)] UInt16 offset; // Flags & Offset
[FieldOffset(8)] Byte ttl; // Time To Live
[FieldOffset(9)] Byte protocol; // Protocol (TCP, UDP, any
other)
[FieldOffset(10)] UInt16 checksum; // IP Header checksum
[FieldOffset(12)] Int64 source; // Source address
[FieldOffset(16)] Int64 destination; // Destination address
};

What I want to do (like I did in C# code) is... Fill all of the structs
fields by using a pointer... In C# I have this code

protected virtual unsafe object[] ParseIPHeader(byte[] packet, int length)
{
short src_port = 0, dst_port = 0;
object[] retval = new object[6];

fixed(byte* packetdata = packet) {
CCommon.IPHeader* ipheader = (CCommon.IPHeader*) packetdata;
// Rest of code goes here...
}

As you can see I fix my pointer and it's initialized with packet's address.
In C# I don't have to use the & operator for an operation like the one shown
above. My problem is that... I want to get the same result in C++.

Object* CRawSocket::parseIPHeader(Byte packet[], int length)[] {
short src_port = 0, dst_port = 0;
System::Text::StringBuilder *src_address, *dst_address;
Object *retval[] = new Object*[6];
src_address = new System::Text::StringBuilder();
dst_address = new System::Text::StringBuilder();

Byte *packeddata = __try_cast< Byte *>(&packet[0]) ;
CCommon::IPHeader *ipheader = (CCommon::IPHeader *) &packeddata;
// Rest of code goes here...
}

I open two instances of VS Debugger (C# & C++ projects). The ipheader points
to packeddata which in turn points to the first element of the array
packet. This works perfectly in C# but it doesn't seem to work in C++. When
I compare both structures (C# & C++) the information contaned in them is
totally different when the data received from the socket is the same.


TIA


Ben Schwehn said:
fixed(byte* packetdata = &packet) // wrong!

but in the C++ world I need to pass the address

I've tried this...

I'm not entirly sure what you're trying to do but instead of c#'s fixed
what you'll probably want to do is use __pin something like

int __pin* p = &packet[0];

to get the address of packet and also pin the entire array

hth
 
B

Ben Schwehn

I would either use __pin to get an raw pointer and then use an unmanaged
native c++ struct (not a __value class) to reinterpret_cast to, or use
Marshal::ptrToStructure to get a managed struct. Don't know if this
helps you at all, sorry if it does not.
 

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

Top