A failing oif C#?

K

Ken Allen

I have been using C# for some time now, and for the most part I am very
impressed, and prefer using it over C++. There is one area where C#/.Net
seem, at least to me, to be less than desirable compared to C/C++, and
that is in the area of communication with buffer mappings. I know about
interop, and have programmed a significant amount of code this way, but
it is a real pain compared to using C++, unless I am missing something,
which is quite possible.

My current problem domain is using pass-through commands to control a
SCSI device. It does not matter what the device is, as the issues I am
attempting to deal with are generic in nature.

The SCSI command protocol supports commands of various fixed length,
from 6 to 12 bytes. Many of the bytes have individual meaning, some have
per-bit meanings, and in other cases more than one byte are combined to
have meaning. For example, consider the 10-byte READ command, which is
defined as follows:

28 XX LL LL LL LL 00 TL TL 00

Where:
28 - is the 10-byte read command in hex
XX - is a byte where
bits 0:2 are reserved
bit 3 is the FUA bit
bit 4 is the DPO bit
bits 5-7 are the LUN (typically zero)
LL - these four bytes represent the logical block address
TL - these two bytes inidicate the number of sectors to be read

In C++ it is fairly simple, albeit tedious, to define a structure for
each of the different command structures, cast the actual command buffer
address to the appropriate structure pointer, and then fill in the
command buffer with some informative code. In C# the structures can each
be defined, but then one has to marshal the data into the buffer; there
does not seem to be any effective method by which the code can convert
the structure into a byte array, or vice versa.

While the commands can be handled using member functions that take
parameters and convert the information directly into a byte array, that
approach is not so clean for the results of a SCSI command.

Consider the MODE SENSE command, which can return one or more pages of
information. The return buffer is a byte stream that contains special
structures which are optionally present. For example, there is a buffer
header sructure that describes the overall content of the buffer,
followed by the specified number of data pages, which each have a
special header that identifies the actual page content, followed by the
page itself. Again, in C++ we can read the byte(s) that define the
specific page and then cast a structure pointer permitting us to access
the contents of the page in a meaningful manner. In C#, we can read the
individual byte(s) to determine the page type, but must then use interop
to copy the information from the buffer into a structure for reference.

Even worse is when I want to use a MODE SELECT command and pass two or
more pages of information. Creating the information in a structure
object (or a class) and then serializing it into the buffer is a pain c
compared to the methods I can use in C++.

Is there no way to avoid all this use of marshalling code to achieve
structured access to the contents of the data buffers? It seems to me
that the amount of code that I have to write to achieve this in C# is
almost twice what I can get away with in C++, which just seems wrong,
somehow. I know that pointers are not part of the C# landscape, but this
need to convert between a structure/class and a byte stream or array
seems to be something that should be made much easier than it is.
Especially because this is 'unsafe' code and must exist in a separate
assembly from my main code (or at least the compiler errors tell me so).

-ken
 
W

wackyphill

You can infact mark a section of your c# code unsafe and use pointers
just like c++.
 
W

Willy Denoyette [MVP]

Ken Allen said:
I have been using C# for some time now, and for the most part I am very
impressed, and prefer using it over C++. There is one area where C#/.Net
seem, at least to me, to be less than desirable compared to C/C++, and that
is in the area of communication with buffer mappings. I know about interop,
and have programmed a significant amount of code this way, but it is a real
pain compared to using C++, unless I am missing something, which is quite
possible.

My current problem domain is using pass-through commands to control a SCSI
device. It does not matter what the device is, as the issues I am
attempting to deal with are generic in nature.

The SCSI command protocol supports commands of various fixed length, from
6 to 12 bytes. Many of the bytes have individual meaning, some have
per-bit meanings, and in other cases more than one byte are combined to
have meaning. For example, consider the 10-byte READ command, which is
defined as follows:

28 XX LL LL LL LL 00 TL TL 00

Where:
28 - is the 10-byte read command in hex
XX - is a byte where
bits 0:2 are reserved
bit 3 is the FUA bit
bit 4 is the DPO bit
bits 5-7 are the LUN (typically zero)
LL - these four bytes represent the logical block address
TL - these two bytes inidicate the number of sectors to be read

In C++ it is fairly simple, albeit tedious, to define a structure for each
of the different command structures, cast the actual command buffer
address to the appropriate structure pointer, and then fill in the command
buffer with some informative code. In C# the structures can each be
defined, but then one has to marshal the data into the buffer; there does
not seem to be any effective method by which the code can convert the
structure into a byte array, or vice versa.

While the commands can be handled using member functions that take
parameters and convert the information directly into a byte array, that
approach is not so clean for the results of a SCSI command.

Consider the MODE SENSE command, which can return one or more pages of
information. The return buffer is a byte stream that contains special
structures which are optionally present. For example, there is a buffer
header sructure that describes the overall content of the buffer, followed
by the specified number of data pages, which each have a special header
that identifies the actual page content, followed by the page itself.
Again, in C++ we can read the byte(s) that define the specific page and
then cast a structure pointer permitting us to access the contents of the
page in a meaningful manner. In C#, we can read the individual byte(s) to
determine the page type, but must then use interop to copy the information
from the buffer into a structure for reference.

Even worse is when I want to use a MODE SELECT command and pass two or
more pages of information. Creating the information in a structure object
(or a class) and then serializing it into the buffer is a pain c compared
to the methods I can use in C++.

Is there no way to avoid all this use of marshalling code to achieve
structured access to the contents of the data buffers? It seems to me that
the amount of code that I have to write to achieve this in C# is almost
twice what I can get away with in C++, which just seems wrong, somehow. I
know that pointers are not part of the C# landscape, but this need to
convert between a structure/class and a byte stream or array seems to be
something that should be made much easier than it is. Especially because
this is 'unsafe' code and must exist in a separate assembly from my main
code (or at least the compiler errors tell me so).

-ken

You use the wrong language/framework for the Job, why not stick with C++ for
this?

Willy.
 
K

Ken Allen

You can infact mark a section of your c# code unsafe and use pointers
just like c++.
How does one mark a section unsafe and have the code before and after
that section as safe (managed) code?

How does one use pointers at all in C#? Even in unsafe code? If I have a
buffer, which is probably defined as a byte array, how do I 'cast' a
subset of that array to be treated as a structure with data members? The
only way I have seen is to marshal a (cast as IntPtr) specific subset of
the array into a structure.

-ken
 
K

Ken Allen

Perhaps, but one must do as one must when a corporate standard is
imposed; in this case, the decision was made to use C# for a specific
set of projects, partially as an exercise to determine where all of the
'bones were buried' and to determine whether C# should be used for
corporate projects at all.

-ken
 
J

Jay B. Harlow [MVP - Outlook]

Ken,
On the flip side to Willy's comments: It sounds like you are using wrong
project for the pilot. If this is a pilot project, I hope this project
typifies other corporate projects, otherwise you may be throwing out the
correct tool (C#), based on attempting to implement the wrong project.

I find it "Better" to use the correct tool for the correct job, rather then
attempt to show horn all jobs into a single tool. Of course its also
important not to collect TOO many tools...

In this case use C# for corporate projects, except were it makes sense to
use C++ for a class library or two...

Hope this helps
Jay

| Perhaps, but one must do as one must when a corporate standard is
| imposed; in this case, the decision was made to use C# for a specific
| set of projects, partially as an exercise to determine where all of the
| 'bones were buried' and to determine whether C# should be used for
| corporate projects at all.
|
| -ken
|
| Willy Denoyette [MVP] wrote:
| > | >
| > <snip/>
| >>
| >>-ken
| >
| >
| > You use the wrong language/framework for the Job, why not stick with C++
for
| > this?
| >
| > Willy.
| >
| >
| >
| >
 
W

Willy Denoyette [MVP]

Well IMO this "One tool fits it all" approach won't work. Most complex
projects or what you call 'corporate projects' will need more than one
language for the job, simply because one language is better suited for a
specific programming task than another.
The same is true for frameworks like .NET, some task will fit perfectly in
this environment, while others can't tolerate the presence of a runtime
component like the CLR (think of Kernel components, drivers etc..). Others
tasks will require a mixture of languages and frameworks, and in my opinion
your project will need the inclusion of C++, maybe managed maybe native, for
the task at hand. Note I'm talking about tasks, not complete projects.
IMO it's perfectly possible to have a mixture of C# and C++, where the C++
is better suited for low level device oriented C style API's usage, where
efficiency, both in terms of space (memory, CPU resources) and time (spent
in transitions between managed and unmanaged code/memory), is more important
than rapid development cycles where C# might be the tool of choice.
Note also that I didn't say it's not possible to use C# to drive some low
level stuff, I only said it's not the right tool to use and it might lead to
frustration when thing tend to be harder than expected.

Willy.
 
M

Matt

Ken said:
How does one mark a section unsafe and have the code before and after
that section as safe (managed) code?

How does one use pointers at all in C#? Even in unsafe code? If I have a
buffer, which is probably defined as a byte array, how do I 'cast' a
subset of that array to be treated as a structure with data members? The
only way I have seen is to marshal a (cast as IntPtr) specific subset of
the array into a structure.

-ken

You can do anything in unsafe code, including writing C++ (more or
less) code:

unsafe
{
char s[200];
int x = 10;
memcpy(
 
W

Willy Denoyette [MVP]

Matt said:
Ken said:
How does one mark a section unsafe and have the code before and after
that section as safe (managed) code?

How does one use pointers at all in C#? Even in unsafe code? If I have a
buffer, which is probably defined as a byte array, how do I 'cast' a
subset of that array to be treated as a structure with data members? The
only way I have seen is to marshal a (cast as IntPtr) specific subset of
the array into a structure.

-ken

You can do anything in unsafe code, including writing C++ (more or
less) code:

unsafe
{
char s[200];
int x = 10;
memcpy(

No it's not, you can't call (not directly) unmanaged code like memcpy(...),
calling unmanaged code from C# is only possible through PInvoke and COM
interop.
unsafe doesn't mean "native" it's simply an indication that the block may
contains native C style pointers and can perform pointer arithmetics but
that's it, the code remains managed (compiled to IL) code and the data like
a char array is still GC heap allocated and JIT tracked data.


unsafe {
// allocates a managed array of type char
char[] s = new char[200];
// pin the array object and take the address of the first char in the array
fixed (char* ptr = &s[0])
{
// use ptr f.i as an argument in a call to unmanaged code using
PInvoke interop

}// un-pin the char array!!!
}

Willy.
 
M

Matt

Willy said:
Matt said:
Ken said:
(e-mail address removed) wrote:
You can infact mark a section of your c# code unsafe and use pointers
just like c++.

How does one mark a section unsafe and have the code before and after
that section as safe (managed) code?

How does one use pointers at all in C#? Even in unsafe code? If I have a
buffer, which is probably defined as a byte array, how do I 'cast' a
subset of that array to be treated as a structure with data members? The
only way I have seen is to marshal a (cast as IntPtr) specific subset of
the array into a structure.

-ken

You can do anything in unsafe code, including writing C++ (more or
less) code:

unsafe
{
char s[200];
int x = 10;
memcpy(

No it's not, you can't call (not directly) unmanaged code like memcpy(...),
calling unmanaged code from C# is only possible through PInvoke and COM
interop.

Yes, I know. I was trying to delete that line and write my own copymem
when I hit "post" instead of return. Sorry about that. You are
absolutely right, of course.
unsafe doesn't mean "native" it's simply an indication that the block may
contains native C style pointers and can perform pointer arithmetics but
that's it, the code remains managed (compiled to IL) code and the data like
a char array is still GC heap allocated and JIT tracked data.

Yep. The point was that you *could* do what he wanted, using unsafe
code, if you really wanted to. I could think of a lot better ways to do
it, tho. Writing a single class to map each object to a block of
memory, and using the various conversion methods to extract the data
would be best.

Matt
unsafe {
// allocates a managed array of type char
char[] s = new char[200];
// pin the array object and take the address of the first char in the array
fixed (char* ptr = &s[0])
{
// use ptr f.i as an argument in a call to unmanaged code using
PInvoke interop

}// un-pin the char array!!!
}

Willy.
 
S

Stef Mp

Hmm seems i'm qute late :)

Anyway , with unsafe code you can allocate things on stack
and do things faster ... pointer arrays are 2-3x faster on read/write
than normal managed arrays:)

unsafe void UnsafeTest()
{
//allocate on stack
byte* p= stackalloc byte[100];
uint* p2=(uint*)p;
uint v1=*p;
uint v2=p[12]+p2[11];

//allocate on unmanaged mem pool
uint
*unmanaged_mem=System.Runtime.InteropServices.Marshal.AllocCoTaskMem(200
).ToPointer();

//free it too
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(new
IntPtr(unmanaged_mem));
}

but indeed , c# is not the best language to use with that kind of code.
I prefer c# over c++ a lot (actualy i can't compile and/or read c++ code
; a mess of macro games and missing .h files..) so i use c# for (almost)
all my lowlevel code and i can tell teht it is as fast as c++ when you
use static functions , pointers and no .net clases.

If you like C# syntax but want it for something low level try the D
language.It is a litl bit faster that C++ , has C# style code , uses
modules/namespaces the same way c# does [almost] and has full
asm/pointer support (the GC can be turned off).

drkIIRaziel
 
N

nkohari

Stef:

I'm not quite sure what the purpose of writing C# instead of C++, while
using only static functions, pointers (and thus unsafe blocks), and no
..NET framework classes. Isn't that effectively just writing C++, except
with the added overhead of the CLR? I'm not even sure why you would
prefer the syntax of C# over that of C++ in that situation.

At any rate, for what it's worth, I'd throw my weight onto the side
that says write the native code in C++ as a DLL and P/Invoke it from
managed code as necessary. C# is good for what it was designed for, and
C++ is good for what it was designed for. "When all you have is a
hammer, everything starts to look like a nail..."

Nate
 

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