473,756 Members | 1,823 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Casting of bytes allocated by stackalloc to struct ptr -- It is possible but immediately

Typically, you need the stackalloc when using win32 platform fucntions,
which tell you the amount of memory required for the output structure in the
first call, like GetJob does. The weired thing is that this works:
byte* p = stackalloc byte[size];
JOB_INFO_2* ji2 = (JOB_INFO_2*) p;

But the immediate casting does not:
JOB_INFO_2* ji2 = (JOB_INFO_2*) stackalloc byte[size];

It throws a lot of compilation messages. Peahaps, it is a compiler bug.
May 20 '07 #1
7 3703
"valentin tihomirov" <V_*********@be st.eewrote in message
news:Oe******** *****@TK2MSFTNG P02.phx.gbl...
Typically, you need the stackalloc when using win32 platform fucntions,
which tell you the amount of memory required for the output structure in
the first call, like GetJob does. The weired thing is that this works:
byte* p = stackalloc byte[size];
JOB_INFO_2* ji2 = (JOB_INFO_2*) p;

But the immediate casting does not:
JOB_INFO_2* ji2 = (JOB_INFO_2*) stackalloc byte[size];

It throws a lot of compilation messages. Peahaps, it is a compiler bug.


Why not simply use?

JOB_INFO_2* ps = stackalloc JOB_INFO_2[1];

Willy.

May 20 '07 #2
Because the structure is extended by private fields. Why do you think the
win api designers provide the functions to return output structure size for
the user to allocate the buffer?
May 21 '07 #3
"valentin tihomirov" <V_*********@be st.eewrote in message
news:uB******** *****@TK2MSFTNG P05.phx.gbl...
Because the structure is extended by private fields. Why do you think the
win api designers provide the functions to return output structure size
for the user to allocate the buffer?
True, I didn't look at this particular struct in detail. Anyway in this case
I would not use stackallock, stack alloc is great when you have to deal with
small structs of blittable types.
I would rather use Marshal.AllocHG lobal to allocate the buffer and use
Marshal.PtrToSt ruct() to marshal the buffer to a managed representation of
the struct. This way I don't need to resort to unsafe code constructs, and I
don't have to marshal the individual fields of the unmanaged buffer to their
managed representation.
If you really want your unmanaged buffer to be stack allocated, you can
always declare it like this:

... int jobs;
int bNeeded;
// Get buffer size needed
ret = EnumJobs(hPrint er, 0, 1, 2, IntPtr.Zero, bNeeded, out bNeeded, out
jobs);
if(ret )
{
void* buffer = stackalloc byte[bNeeded];
EnumJobs(hPrint er, 0, 1, 2, ptr, bNeeded, out bNeeded, out jobs);
IntPtr ptr = new(buffer);
Marshal.PtrToSt ruct(ptr, ...);
..
Willy.

May 21 '07 #4
Ok, I will tell you why marshalling is bad for p/invoking. Let me
demonstrate on the GetJob/SetJob example.

[1]

At first, DEVMODE is referred by pointer in JOB_INFO_2. But in .net, we
cannot use UnmanagedType.L PStruct:
[MarshalAs(Unman agedType.LPStru ct)] public DEVMODE pDevMode;

All the pointers to structures must be declared as opaque IntPtr. Thus, when
I unmarshal result of GetJob, the IntPtr devMode field will have some value
to be unmarshalled separately. After getting the print job settings, I
update the fields of interest and use SetJob to apply the updated settings
to the system. The SetJob invokation must be preceded by unmanaged space
allocation and marshalling. It will be done twice again (for job_info and
devmode). Furthermore, the IntPtr devMode field must be updated explicitly
accordingly.

As a conclustion, I have to do 22 lines of code, multiple heap memory
allocations and copy, where normally 2 lines of code with stack alloc and no
data copying suffices.
In addition to the code bloating, marshalling is not just possible in many
cases, since it requires exact structure descriptions. Take the
GetJob/SetJob example. I got the job settings into a structure, updated some
fields of it and wrote it back leaving other printing settings untouched.
The first two fields of DEVMODE are structure size and extra size. I do not
have the declarations of the extra fields. So Marshal.SizeOf( myDevMode) will
return a size smaller than specified in the size fields of the structure.
The spooler will fail on SetJob accessing the not described and thus not
allocated/marshaled fields.

Marshaling makes your code cumbersome and fragile.
May 21 '07 #5
"valentin tihomirov" <V_*********@be st.eewrote in message
news:eu******** ******@TK2MSFTN GP06.phx.gbl...
Ok, I will tell you why marshalling is bad for p/invoking. Let me
demonstrate on the GetJob/SetJob example.

[1]

At first, DEVMODE is referred by pointer in JOB_INFO_2. But in .net, we
cannot use UnmanagedType.L PStruct:
[MarshalAs(Unman agedType.LPStru ct)] public DEVMODE pDevMode;

All the pointers to structures must be declared as opaque IntPtr. Thus,
when I unmarshal result of GetJob, the IntPtr devMode field will have some
value to be unmarshalled separately. After getting the print job settings,
I update the fields of interest and use SetJob to apply the updated
settings to the system. The SetJob invokation must be preceded by
unmanaged space allocation and marshalling. It will be done twice again
(for job_info and devmode). Furthermore, the IntPtr devMode field must be
updated explicitly accordingly.

As a conclustion, I have to do 22 lines of code, multiple heap memory
allocations and copy, where normally 2 lines of code with stack alloc and
no data copying suffices.
In addition to the code bloating, marshalling is not just possible in many
cases, since it requires exact structure descriptions. Take the
GetJob/SetJob example. I got the job settings into a structure, updated
some fields of it and wrote it back leaving other printing settings
untouched. The first two fields of DEVMODE are structure size and extra
size. I do not have the declarations of the extra fields. So
Marshal.SizeOf( myDevMode) will return a size smaller than specified in the
size fields of the structure. The spooler will fail on SetJob accessing
the not described and thus not allocated/marshaled fields.

Marshaling makes your code cumbersome and fragile.

All depends on the usage scenario, on what structure you have to deal with,
what fields you need to use in your code in managed form, for instance if
you need to get at the items declared as LPTSTR you'll have to marshal these
to a System.String anyway.
I agree that in your scenario, where you only need the raw structure to
modify some fields and pass this back to another API, you can go without
marshaling, however, I don't like unsafe constructs.
I agree, that some Win32 structs are hard to marshal, this is where C style
data types meets OO style (and this is also a reason why some Win32 API's
are not wrapped in the FCL), dealing with API's designed for "C " from other
languages is by itself cumbersome and fragile.
That's why I wouldn't use C# to access the spooler API's, I would use
C++/CLI. This is also what MS is doing, some of the new FCL classes are now
written using managed C++, it's easier to get it right, especially when you
have to deal with a lot of (OS version dependent) API's and structures, much
is taken care of in the header files. I wonder how much of the FCL would
have been written using C# if C++/CLI had been available since day one?

Willy.
Willy.

May 21 '07 #6
"valentin tihomirov" <V_*********@be st.eeschrieb im Newsbeitrag
news:Oe******** *****@TK2MSFTNG P02.phx.gbl...
Typically, you need the stackalloc when using win32 platform fucntions,
which tell you the amount of memory required for the output structure in
the first call, like GetJob does. The weired thing is that this works:
byte* p = stackalloc byte[size];
JOB_INFO_2* ji2 = (JOB_INFO_2*) p;

But the immediate casting does not:
JOB_INFO_2* ji2 = (JOB_INFO_2*) stackalloc byte[size];

It throws a lot of compilation messages. Peahaps, it is a compiler bug.
Following the specification of C# the stackalloc construct can only be used
as variable initializer. Maybe its only meant for declaring 'unsafe
variables'.

Christof
May 22 '07 #7
"Christof Nordiek" <cn@nospam.dewr ote in message
news:%2******** ********@TK2MSF TNGP04.phx.gbl. ..
"valentin tihomirov" <V_*********@be st.eeschrieb im Newsbeitrag
news:Oe******** *****@TK2MSFTNG P02.phx.gbl...
>Typically, you need the stackalloc when using win32 platform fucntions,
which tell you the amount of memory required for the output structure in
the first call, like GetJob does. The weired thing is that this works:
byte* p = stackalloc byte[size];
JOB_INFO_2* ji2 = (JOB_INFO_2*) p;

But the immediate casting does not:
JOB_INFO_2* ji2 = (JOB_INFO_2*) stackalloc byte[size];

It throws a lot of compilation messages. Peahaps, it is a compiler bug.

Following the specification of C# the stackalloc construct can only be
used as variable initializer. Maybe its only meant for declaring 'unsafe
variables'.

Christof
This is not the point, JOB_INFO_2* is an unsafe variable (it's a pointer
variable).
JOB_INFO_2* ptr = stackalloc JOB_INFO_2[2]
compiles just fine, the point is that the compiler doesn't like the cast in:
JOB_INFO_2* ptr = (JOB_INFO_2*)st ackalloc byte[sizeofjob_info_ 2];
I don't know if it's a bug, looks more like a missing feature. Anyway not
quite a big issue, the bypass is illustrated by the OP.

Willy.

May 22 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3478
by: Jacob Jensen | last post by:
This question has probably been asked a million time, but here it comes again. I want to learn the difference between the three type cast operators: static_cast, reinterpret_cast, dynamic_cast. A good way to do this is by example. So I will give an example and please tell me what you think: I have a base class A with a virtual destructor, and a class B that is it inherits publicly from A and defines som extra stuff.
5
9744
by: Alex Vinokur | last post by:
"Richard Bos" <rlb@hoekstra-uitgeverij.nl> wrote in message news:4180f756.197032434@news.individual.net... to news:comp.lang.c > ben19777@hotmail.com (Ben) wrote: > > 2) Structure casted into an array of char > > typedef struct { > > char name; > > int age; > > int id; > > } person; > >
19
2867
by: becte | last post by:
I need to use three bytes to store four 6-bit integers (4 * 6 = 3 * 8) like this 11111122|22223333|33444444 Suppose the input is, int c1, c2, c3, c4, range 0 .. 2^6 -1 and the output is int o1,o2,o3, range 0 .. 2^8-1 How to do this in a clever way? (The 6 bits integers represent characters in range A-Z and 0-9)
231
23217
by: Brian Blais | last post by:
Hello, I saw on a couple of recent posts people saying that casting the return value of malloc is bad, like: d=(double *) malloc(50*sizeof(double)); why is this bad? I had always thought (perhaps mistakenly) that the purpose of a void pointer was to cast into a legitimate date type. Is this wrong? Why, and what is considered to be correct form?
20
2113
by: j0mbolar | last post by:
I was reading page 720 of unix network programming, volume one, second edition. In this udp_write function he does the following: void udp_write(char *buf, <everything else omitted) struct udpiphdr *ui; struct ip *ip; ip = (struct ip *) buf;
6
2842
by: Daniel O'Connell | last post by:
Two questions here: 1. Is there any particular reason why when using stackalloc, the code byte *buffer = stackalloc byte; works, but code like byte *buffer; buffer = stackalloc byte; is considered incorrect syntax? Was this an oversight, a stylistic design, or is there a technical reason it won't work? 2. I was reading an older(circa 2000) question posted to one of these groups in which Eric Gunnerson mentions that the C# team was...
12
8127
by: Olaf Baeyens | last post by:
I am porting some of my buffer class code for C++ to C#. This C++ class allocates a block of memory using m_pBuffer=new BYTE; But since the class is also used for pointers for funtions that uses raw MMX and SSE power, the starting pointer MUST be starting at a 16 byte memory boundary. In C++ I allocate more memory than needed, and in a second phase I search for the address that starts on a 16 byte boundary. And I then use that new...
3
1748
by: LongBow | last post by:
Hello all, First of all, sorry for multiple question per one thread. I have two questions. First what I think might be the easier problem. I am capturing data from an embedded device which I need to display data. One particular piece of data is a 32 bit floating point value. The problem I am having is converting the 4-byte value which is read via an RS-232 link. How can I cast the 4-byte value to a value type float correctly? I have...
11
4717
by: redefined.horizons | last post by:
First, I would thank all of those that took the time to answer my question about creating an array based on a numeric value stored in a variable. I realize after reading the responses and doing some more research, that what I really need is known in C as a "dynamic array". Basically, you surpass the array notation and use pointers with memory obtained with malloc() or calloc(). I think this will do just what I needed. That has brought...
0
9275
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10040
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9846
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8713
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6534
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5304
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3806
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3359
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2666
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.