Pointers in C#? - c#

In one C# maintenance project I came across following variable declaration:
Int32* iProgressAddress;
Is it pointer declaration in C#?
I thought that there is no pointer concept in C#, what does that statement mean?

C# does support pointers, but it's limited to pointing to primitive data types that are unmanaged types, such as ints, floats, enums, and other pointer types (plus the rest of the primitives).
edit: as well as value types

Yes, it is.
Notice, that the method is marked unsafe. As well as the assembly.
There is a lot of things to know before using pointers from the managed code.
For instance, pointer pinning.

I'm sorry, I'm afraid that's a pointer, and you have to get used to it.
REALLY! Pointers aren't that scary. :)

Related

Where are pointers used in C#?

I am pretty new to C# environment, I have been coding in C++ for a while now. Where exactly will one use pointers in C#? IS it advisable to use pointers in C#?
You can use pointers, but only in "unsafe" mode. You will never use them in normal C# coding.
All classes inherit from Object and are called "Reference" types. These types are passed by reference, which is mainly just a pointer under the hood, and hides any details like addresses from the programmer.
These are your "pointers" but you never delete them because everything in C# is garbage collected, and you access them as if you had the object itself (no -> operator).
Types like int, double, and char are "Value" types and are passed by value (just like in C++). You can also pass these by reference, but you have to use the ref keyword in the function signature and when calling it.
struct is the other special case where it is a "Value" type. MSDN
The only place that you can actually use pointers in C# is in unsafe regions of code which is generally frowned upon. The rest of the time, the runtime will manage memory for you.

Create COM interface returning a pointer that is marshalled as IntPtr in C#

I want to declare a COM Interface in MIDL that allows for returning a pointer (like in the ID3D11Blob). I understand that pointers are a special thing in COM because of the stubs generated for RPC calls. I do not need RPC, but only want to access the COM server from C#. The question is: can I declare the interface in such a way that the C# stub returns an IntPtr? I have tried to add [local] to enable void pointers, but that does not suffice.
The interface should look in MIDL like
[local] void *PeekData(void)
and in C# like
IntPtr PeekData()
Is this possible? If so, how?
Thanks in advance,
Christoph
Edit: To rephrase the question: Why is
HRESULT GetData([in, out, size_is(*size)] BYTE data[], [in, out] ULONG *size);
becoming
void GetData(ref byte, ref uint)
and how can I avoid the first parameter becoming a single byte in C#?
This goes wrong because you imported the COM server declarations from a type library. Type libraries were originally designed to support a sub-set of COM originally called "OLE Automation". Which restricts the kind of types you can use for method arguments. In particular, raw pointers are not permitted. An array must be declared as a SAFEARRAY. Which ensures that the caller can always index an array safely, safe arrays have extra metadata that describes the rank and the lower/upper bounds of the array.
The [size_is] attribute is only understood by MIDL, it is used to create the proxy and the stub for the interface. Knowing how many elements the array contains is also important when it needs to be copied into an interop packet that's sent on the wire to the stub.
Since type libraries don't support a declaration like this, the [size_is] attribute is stripped and the type library importer only sees BYTE*. Which is ambiguous, that can be a byte passed by reference or it can be a pointer to an array of bytes. The importer chooses the former since it has no hope of making an array work, it doesn't know the size of the array. So you get ref byte.
To fix this issue, you have to alter the import library so you can provide the proper declaration of the method. Which requires the [MarshalAs] attribute to declare the byte[] argument an LPArray with the SizeParamIndex property set so you can tell the CLR that the array size is determined by the size argument. There are two basic ways to go about it:
Decompile the interop library with ildasm.exe, modify the .il file and put it back together with ilasm.exe. You'd use a sample C# declaration that you look at with ildasm.exe to know how to edit the IL. This is the approach that Microsoft recommends.
Use a good decompiler that can decompile IL back to C#. Reflector and ILSpy are popular. Copy/paste the generated code into a source file of your project and edit the method, applying the [MarshalAs] attribute. Advantage is that editing is easier and you no longer have a dependency on the interop library anymore.
In either case, you want to make sure that the COM server is stable so you don't have to do this very often. If it is not then modifying the server itself is highly recommended, use a safe array.
I think I found the solution on http://msdn.microsoft.com/en-gb/library/z6cfh6e6(v=vs.110).aspx#cpcondefaultmarshalingforarraysanchor2: This is the default behaviour for C-style arrays. One can avoid that by using SAFEARRAYs.

CONSOLE_SCREEN_BUFFER_INFO gives an error

In my C# console application, I'm having an error for this structure:
The error message seems fairly clear - where were you expecting the type to come from? It looks like you're basically missing the declaration of the struct, which you can take from PInvoke.NET.
Basically, P/Invoke is a way of exposing native library calls to managed code, but for complex types, you need a managed representation of the type - and .NET doesn't come with a representation of CONSOLE_SCREEN_BUFFER_INFO, so you have to declare it yourself. PInvoke.NET contains a lot of these declarations, as well as the declarations for the functions that use them. (They're not always accurate, but in my experience they usually are.)

MarshalAs attribute case study

When should we use this attribute and why do we need it? For example, if the native function in c takes as a parameter a pointer to unsigned char, and I know that it's needed to fulfill the array of unsigned chars, why can't I use array of bytes in C# to use this function? Is it necessary to do marshalling?
The runtime will be able to automatically determine how to marshal data between native and managed code in most cases, so you generally don't need to specify the attribute. MarshalAs is only necessary when there is an ambiguity in the definition (and you want to tell the runtime precisely how to marshal the data) or if you require non-default behaviour.
In my experience, MarshalAs is only really required when working with strings, since there are so many different representations in native code; unicode/ansi, c-strings or not, etc.
Additional use of MarshalAs attribute is marshalling fixed-size arrays (including fixed-size strings) with ByValArray and SizeConst parameters. For example, many structures from Windows API contain fixed-size strings.
Based on Microsoft documentation for Type marshaling
Marshaling is the process of transforming types when they need to cross between managed and native code. Marshaling is needed because
the types in the managed and unmanaged code are different. In managed
code, for instance, you have a String, while in the unmanaged world
strings can be Unicode ("wide"), non-Unicode, null-terminated, ASCII,
etc. By default, the P/Invoke subsystem tries to do the right thing
based on the default behavior, described on this article. However, for
those situations where you need extra control, you can employ the
MarshalAs attribute to specify what is the expected type on the
unmanaged side.
Generally, the runtime tries to do the "right thing" when marshaling
to require the least amount of work from you.
Which types need special handling is explained on the following link from the doc to Blittable and Non-Blittable Types:
Most data types have a common representation in both managed and
unmanaged memory and do not require special handling by the interop
marshaler. These types are called blittable types because they do not
require conversion when passed between managed and unmanaged code.
Non-blittable types would be the answer to your question. You would have to marshal for the following ones:
Array, Boolean, char, class, object, string, value type (structure), delegates, unmanaged arrays that are either COM-style safe arrays or C-style arrays with fixed or variable length.
Unmanaged structures can also contain embedded arrays or Booleans (non-blittable types). There you have to be careful according the doc:
Structures that are returned from platform invoke calls must be
blittable types. Platform invoke does not support non-blittable
structures as return types.

How to marshal a list in C#

I have to send a list from C# to C++.The C# list is List<string>MyList and the C++ code accepts it as list<wstring>cppList.How to use marshalas for this.
Thanks
It is always wiser not to use complex type marshaling between native code and managed code.
In case of List, these type totally differ from each other as they have different memory layout for each item.
So the best way is to write a utility function in a native dll that accepts array of string(char*) and manually build your native List and ultimately call the desired method. It is easy for your to create wrapper of that utility function.
C# cannot P/Invoke complex C++ types. You will have to use C++/CLI, they might have a method for marshalling it across. Else, you will have to marshal each string across individually.
strings in C# are wstrings (2 byte unicode strings), so if what you say is true, then no special conversions are necessary.

Categories

Resources