Converting a C struct to C# for a P/Invoke call (struct in structs and unions)

  • Thread starter Thread starter Tom Hellström
  • Start date Start date
T

Tom Hellström

Hi, i want to make a call to a dll and I need to pass a pointer that then gets
converted to a struct
via the Marshal.PtrToStructure method. The thing is, the struct is a bit
complicated.

I need some tip on how to get around the union parts and also how to deal with
the #if's at the bottom.
Any ideas?


typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
struct {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
};
POINTL dmPosition;
DWORD dmDisplayOrientation;
DWORD dmDisplayFixedOutput;
};

short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BYTE dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union {
DWORD dmDisplayFlags;
DWORD dmNup;
}
DWORD dmDisplayFrequency;
#if(WINVER >= 0x0400)
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
DWORD dmPanningWidth;
DWORD dmPanningHeight;
#endif
#endif /* WINVER >= 0x0400 */
} DEVMODE;

have a nice summer
///. Tom H
 
Hi Tom,

I won't attempt to answer this myself, but this site might give you a few ideas.

http://www.pinvoke.net/


Hi, i want to make a call to a dll and I need to pass a pointer that then gets
converted to a struct
via the Marshal.PtrToStructure method. The thing is, the struct is a bit
complicated.

I need some tip on how to get around the union parts and also how to deal with
the #if's at the bottom.
Any ideas?


typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
struct {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
};
POINTL dmPosition;
DWORD dmDisplayOrientation;
DWORD dmDisplayFixedOutput;
};

short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BYTE dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union {
DWORD dmDisplayFlags;
DWORD dmNup;
}
DWORD dmDisplayFrequency;
#if(WINVER >= 0x0400)
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
DWORD dmPanningWidth;
DWORD dmPanningHeight;
#endif
#endif /* WINVER >= 0x0400 */
} DEVMODE;

have a nice summer
///. Tom H
 
Tom Hellström said:
Hi, i want to make a call to a dll and I need to pass a pointer that then
gets
converted to a struct
via the Marshal.PtrToStructure method. The thing is, the struct is a bit
complicated.

I need some tip on how to get around the union parts and also how to deal
with
the #if's at the bottom.
Any ideas?


typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
struct {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
};
POINTL dmPosition;
DWORD dmDisplayOrientation;
DWORD dmDisplayFixedOutput;
};

short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BYTE dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union {
DWORD dmDisplayFlags;
DWORD dmNup;
}
DWORD dmDisplayFrequency;
#if(WINVER >= 0x0400)
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
DWORD dmPanningWidth;
DWORD dmPanningHeight;
#endif
#endif /* WINVER >= 0x0400 */
} DEVMODE;

have a nice summer
///. Tom H


Beyond a certian threshold of gruesomeness you might be better off using the
struct in a managed C++ wrapper. The wrapper can interact natively with the
struct and provide managed code with access to the data.

Another option is to figure out the size of the struct and just use a
managed byte array. Then use BitConverter and procedural logic to read and
write the struct. A hybrid approach is to break the struct into several
regions and procedurally marshal them. These approaches use pure C#, but
ironically require a higher level of understanding of C/C++ structs and
unmanaged memory than the C++ wrapper approach, since the C++ compiler
understands the struct for you.

David
 
Hi Morten, thanks for the tip, there where a C# version of the struct at that
site that I could use.
Excellent.


Morten Wennevik said:
Hi Tom,

I won't attempt to answer this myself, but this site might give you a few
ideas.

http://www.pinvoke.net/


Hi, i want to make a call to a dll and I need to pass a pointer that then
gets
converted to a struct
via the Marshal.PtrToStructure method. The thing is, the struct is a bit
complicated.

I need some tip on how to get around the union parts and also how to deal
with
the #if's at the bottom.
Any ideas?


typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
struct {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
};
POINTL dmPosition;
DWORD dmDisplayOrientation;
DWORD dmDisplayFixedOutput;
};

short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BYTE dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union {
DWORD dmDisplayFlags;
DWORD dmNup;
}
DWORD dmDisplayFrequency;
#if(WINVER >= 0x0400)
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
DWORD dmPanningWidth;
DWORD dmPanningHeight;
#endif
#endif /* WINVER >= 0x0400 */
} DEVMODE;

have a nice summer
///. Tom H



----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet
News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+
Newsgroups
 
David Browne said:
Tom Hellström said:
Hi, i want to make a call to a dll and I need to pass a pointer that then
gets
converted to a struct
via the Marshal.PtrToStructure method. The thing is, the struct is a bit
complicated.

I need some tip on how to get around the union parts and also how to deal
with
the #if's at the bottom.
Any ideas?


typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
struct {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
};
POINTL dmPosition;
DWORD dmDisplayOrientation;
DWORD dmDisplayFixedOutput;
};

short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BYTE dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union {
DWORD dmDisplayFlags;
DWORD dmNup;
}
DWORD dmDisplayFrequency;
#if(WINVER >= 0x0400)
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
DWORD dmPanningWidth;
DWORD dmPanningHeight;
#endif
#endif /* WINVER >= 0x0400 */
} DEVMODE;

have a nice summer
///. Tom H


Beyond a certian threshold of gruesomeness you might be better off using the
struct in a managed C++ wrapper. The wrapper can interact natively with the
struct and provide managed code with access to the data.

Another option is to figure out the size of the struct and just use a
managed byte array. Then use BitConverter and procedural logic to read and
write the struct. A hybrid approach is to break the struct into several
regions and procedurally marshal them. These approaches use pure C#, but
ironically require a higher level of understanding of C/C++ structs and
unmanaged memory than the C++ wrapper approach, since the C++ compiler
understands the struct for you.

David

Well, I got hold of a C# version of the struct, but I ran into some other
problems, where
your tip about splitting it up and marshaling the separate pices worked fine.

Thanks,
///. Tom
 
Back
Top