I have an unmanaged code which is a type of:
unsigned long *inputParameters
I need to convert my variable inputparameters to C# type
ulong[] inputParameters
I've tried different types of conversions like
auto inputParams = *((unsigned long*)inputParameters)
&inputParameters
however I am getting this exception:
cannot convert argument from 'unsigned long *' to 'cli::array<unsigned __int64,1> ^'
Any types known in C# as reference types, need to be instantiated by using the gcnew keyword, arrays being no exception. Most value types are marashalled behind the scenes, so you can generally just assign managed to unmanged and vice versa without any casting or trickery. Magic, I know! There are some exception, but the compiler will let you know if there is an issue.
I am assuming that *inputParameters is a pointer list (rather than a pointer to a single value), which means that you should have a variable that contains the number of elements in the list, lets call it nElements. To do the conversion, you can do the following:
//some test data
int nElements = 10;
unsigned long *inputParameters = (unsigned long *)malloc(sizeof(unsigned long) * nElements);
for (int i = 0; i < nElements; i++)
{
*(inputParameters + i) = i * 2;//just arbitrary values
}
//now create a .NET array (lines below directly solve your question)
array<UInt64, 1>^ managedArray = gcnew array<UInt64, 1>(nElements);
for (int i = 0; i < nElements; i++)
{
tempArray[i] = *(inputParameters + i);//this will be marshalled under the hood correctly.
}
//now the array is ready to be consumed by C# code.
Here, array<UInt64, 1>^ is the C++/CLI equivalent of C#'s ulong[]. You can return managedArray to a method call from C# that expects ulong[] as the return type.
Related
I want to convert a multidimensional array of int[,] to an array of ushort[,] and if possible without looping over each dimension.
I found a post where object[,] is converted to double[,] by using Array.Copy. Unfortunately this only works because the objects are allready of type double. Is there any chance to achieve a similar result for converting int to ushort (assuming it always fits)?
var input = new [,]
{
{1,1,1},
{2,2,2},
{3,3,3}
};
var output = new ushort[3, 3];
// Convert
Array.Copy(input, output, input.Length);
The above code compiles, but fails on execution because it can not convert from int to ushort. I know why this happens, I just want to tell .NET that it should just convert.
As I said I know the easiest solution are two loops. I am just curious if there is an alternative.
Conclusion: Unfortunately there is no fast and built-in way to do this. Therefore I recommend the obvious and readable solution of going for the double loop unless you really need lightning speed fast conversion.
for(var i=0; i<input.GetLength(0); i++)
for(var j=0; j<input.GetLength(1); j++)
output[i,j] = (ushort)input[i,j];
However this is not the accepted solution since for my personal interest I was asking for the fastest alternative and that is, as expected, and evil and unsafe pointer conversion.
This will work without any conversion overhead. Also, it's evil, but I'd do it.
static unsafe void FastCopy(int[,] source, ushort[,] destination)
{
//pin the source and destination arrays
fixed (int* pSource = source) fixed (ushort* pDestination = destination)
{
//compute the pointers for the elements just past the arrays
//as termination conditions
var pSourceEnd = pSource + source.Length;
var pDestinationEnd = pDestination + destination.Length;
//setup our iterator variables
var pSourceCurrent = pSource;
var pDestinationCurrent = pDestination;
//loop over each element until you run out of elements in
//either the source or destination
while (pSourceCurrent < pSourceEnd && pDestinationCurrent < pDestinationEnd)
{
//copy the two lowest bytes in each source int to the
//destination ushort
*pDestinationCurrent++ = *(ushort*)pSourceCurrent++;
}
}
}
Well, you can't convert in-place because arrays are low-level structures, so the memory footprint of an int[,] and a ushort[,] would be different. Also, there's not a built-in method to convert a 2-D array, so the simplest option is to loop and fill a new array with the converted values.
You seem to be conflating very different types of "casts". Do not mix reference conversions with type conversions and boxing conversions:
class Foo: IFoo { ... }
var foo = new Foo();
var iFoo = foo; //implicit reference conversion
var i = 1;
var o = (object)i; //boxing
var u = (uint)i; //type conversion
Reference conversions do not change the object at all, they only change the type of the reference pointing at it. Type conversions (for lack of a better term, english is not my native language) give you back an alltogether different object. Boxing and unboxing conversions are special but behavior wise, in the scope of your question, are similar to reference conversions.
That C# has the same syntax for all these semantically very different casts is, in my opnion, unfortunate.
Array.Copy will allow you to copy between arrays of different type when there is a reference type conversion or boxing/unboxing coversion between them. The reason being that you are not really changing the object, just it's reference (the bits that make up the object stay the same and therefore its size too (again, not strictly true with boxing/unboxing)). That is, the following are all valid:
var foos = new Foo[] { null, null, null };
var iFoos = new IFoo[3];
Array.Copy(foos, iFoos, 3); //reference conversion
var ints = new[] { 1, 2, 3 };
var objs = new object[3];
Array.Copy(ints, objs, 3); //boxing conversion
Array.Copy(objs, ints, 3); //unboxing conversion
While the following is not:
var ints = new[] { 1, 2, 3 };
var uints = new uint[3];
Array.Copy(ints, uints, 3); //type conversion. Runtime error.
Worth noting that the following is also not valid:
var objs = new object[] { 1, 2, 3 }; //boxed int[]
var uints = new uint[3];
Array.Copy(objs, uints, 3); // Unboxing conversion. Runtime error. Huh?
Why is that? Isn't there an unboxing conversion from object to uint? Yes there is, but the boxed value is really an int and you can only unbox a boxed value to its real type. Due to the same reason, the following will also give you a runtime error:
obect i = 1;
var u = (uint)i;
So what does that have to do with anything you've asked?
Well, that there is no inbuilt way to convert a n-dimensional array from one type array to another if the conversion is not a simple reference or boxing/unboxing conversion. You either have to flatten the array using Linq or create your own extension method and in either case you will have to iterate the array to perform the conversion because you have to create a new object (potentially with different size, bits, etc.) for each element in the source array.
Obviosuly, performance will be significantly slower than Array.Copy.
While learning C#, this question came to my mind. What is the difference between void and var?
Here are the two example I would like to share:
void * voidInt = (void *) 7;
void * voidChar = (void *) 'F';
void * voidCharArray = (void *) "AbcString";
And this is example of var:
var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";
Is void an anonymous datatype?
If yes, then what is the major
difference between var and void?
Can someone help me clear this situation?
The other answers here are pretty good but I think they do not get clearly to the fundamentals. It is the fundamentals you are confused about, so let's address those.
A variable is a storage location that contains a value.
A variable is associated with a type.
A local variable has a name.
So voidInt, voidChar, voidCharArray, varInt, varChar and varCharArray are all variables, and they all have types associated with them. Each variable can be assigned a value of that type or produce a value of that type, depending on whether the variable is being written to or read from.
OK, so now what are pointers?
A type has a corresponding pointer type. (Note that in unsafe C# only the unmanaged types have corresponding pointer types.)
The void * type is a special pointer type.
A pointer is a value.
A pointer of type T* may be dereferenced to produce a variable of type T. T* must not be void*.
A pointer may be explicitly converted to or from any integral type, though these operations are permitted to lose information and are dependent on implementation details.
Any pointer value may be implicitly converted to void*.
Any void* value may be explicitly converted to any pointer type value.
And what is var in C#?
var is a "syntactic sugar" that tells the compiler to deduce the type of the variable from the initialzier rather than requiring that it be written out.
And what are "anonymous types" in C#?
Some expressions in C# have a type that is not declared and has no name; these are known as the "anonymous" types.
So now we can look at your program and see what each line does.
void * voidInt = (void *) 7;
voidInt is a variable of type void*. The value assigned to it is the conversion of the integer 7 to a pointer, which is almost certainly a garbage pointer on any modern operating system. This code is essentially nonsensical.
More sensible code would be:
int myInt = 7;
int* intPtr = &myInt;
void* voidInt = intPtr;
This means that myInt is a variable which holds the value 7, intPtr is a variable which holds a pointer; when that pointer is dereferenced it produces variable myInt. voidInt is a variable which holds any pointer, and the value read from intPtr is a pointer. So now voidInt and intPtr both hold a pointer to variable myInt.
void * voidChar = (void *) 'F';
Same thing here. The character F is treated as a number and converted to a pointer value, which is stored in the variable. This is not sensible. Sensible code would be something like:
char myChar = 'F';
void *voidChar = &myChar;
But this makes perfect sense:
void * voidCharArray = (void *) "AbcString";
A string literal in C++ is convertible to a char* which is a pointer to the storage for the first character, and that pointer is convertible to void*.
What about this?
var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";
This is just a pleasant way to write
int varInt = 7;
char varChar = 'F';
string varCharArray = "AbcString";
Each variable has its given type, and each assignment stores a value of that type in the variable.
What about anonymous types?
var anon = new { X = 123, Y = 456 };
This makes a variable of anonymous type, where the anonymous type has two properties X and Y both of type int. The type has no name, so there is no way to write out the type in the declaration, hence var must be used.
The key thing here is to make sure that you have a grasp of the fundamentals: pointers are values, they may be dereferenced, and doing so produces a variable. Since pointers are values they may themselves be stored in variables of pointer type. This has almost nothing to do with var, which is a pleasant way in C# to make the compiler do the work of figuring out what type a variable should have.
void and var do not really have anything in common:
void (as used by pointer variables in C and C++) means an unspecified (not a definite) type. void* aren't permitted* in managed C# (although a very weak type, such as an object reference might be a close approximation). Generally, void* types need to be re-cast in order to be useful.
However void return types from a method / function mean the same
in both languages, which is to convey that there is no return value (like Unit in Scala)
In contrast, var in C# defines an implicitly typed variable - the variable still has a strong type, but the actual type is inferred from the right hand side at compile time.
e.g.
var v1 = "Foo"; // v1 is a string, because it is inferred from the right hand side
var v2 = XDocument.Parse(#"c:\temp\foo.xml"); // v2 is the return type of the function
var is often required when using anonymous types - this is probably where you've made the connection between var and anonymous types:
var v3 = new { Name = "Foo", Value = 123}; // v3 is strongly typed, anonymous class.
var is especially useful for assigning variables to the return values of LINQ expressions, where the types can be quite complex:
var v3 = db.Persons
.Join(db.Cities, p => p.CityId, c => c.Id, (p, c) => new {Person = p, City = c})
.GroupBy(pc => pc.City.Name);
* Actually, that's not entirely true, you can use void* in C# with unsafe
Edit
One further thing worth mentioning, that as of C#6, that implicit var typing can only be used for local variables, i.e. C# doesn't support implicit typing of method return types (unlike functional languages like Scala, where the compiler in most instances can also infer the return type of a method).
In an unsafe context, the equivalent of C++ void* in C# is void*. Any data pointer type can be assigned to a void*.
In a safe context, object is (loosely) the corresponding concept. Any class/interface/struct instance can be assigned to it.
The equivalent of C# var in C++ is auto. When used to declare and initialize a local variable, it acts as the type of the expression assigned to that variable, if that is possible.
You can do this with c++ void pointer:
void * val = (void *) 7;
val = (void *) "Abcd";
But you cannot do this with c# var:
var val = 7;
val = "abcd";
This will throw an error.
Update
If you want to achieve similar behavior of void * you can use dynamic.
dynamic val = (dynamic) 7;
val = (dynamic) "ABC";
When var is used, the actual type of the variable is determined at compile time. But, when dynamic is used, the actual type of the variable is determined at run time.
I have just asked and obtained an answer to my question that was : "can't return custom type instance with unmanaged export (Robert Giesecke)" -> can't return custom type instance with unmanaged export (Robert Giesecke)
I wonder if (and how) it is possible to pass arrays of struct from .NET to Delphi using unmanaged export (Robert Giesecke):
Returning arrays directly like
[DllExport] public static void CreateSampleInstance(out Sample[] sample)
using array member in a returned struct
[DllExport] public static void CreateSampleInstance(out Sample sample)
and
`public struct Sample
{
Other[] Others;
}`
My question here is how to write the Delphi side and what attribute to set in the .NET one.
Thanks a lot.
Arrays are more tricky because you need to take more care over where the array is allocated and destroyed. The cleanest approach is always to allocate at the caller, pass the array to the callee to let it fill out the array. That approach would look like this in your context:
public struct Sample
{
[MarshalAs(UnmanagedType.BStr)]
public string Name;
}
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
Sample[] samples,
ref int len
)
{
// len holds the length of the array on input
// len is assigned the number of items that have been assigned values
// use the return value to indicate success or failure
for (int i = 0; i < len; i++)
samples[i].Name = "foo: " + i.ToString();
return 0;
}
You need to specify that the array needs to be marshalled in the out direction. If you wanted values marshalled both ways then you would use In, Out instead of Out. You also need to use MarshalAs with UnmanagedType.LPArray to indicate how to marshal the array. And you do need to specify the size param so that the marshaller knows how many items to marshal back to the unmanaged code.
And then on the Delphi side you declare the function like this:
type
TSample = record
Name: WideString;
end;
PSample = ^TSample;
function func(samples: PSample; var len: Integer): Integer; stdcall;
external dllname;
Call it like this:
var
samples: array of TSample;
i, len: Integer;
....
len := 10;
SetLength(samples, len);
if func(PSample(samples), len)=0 then
for i := 0 to len-1 do
Writeln(samples[i].Name);
Update
As AlexS discovered (see comments below), passing the size param index by reference is only supported on .net 4. On earlier versions you need to pass the size param index by value.
The reason I chose to pass it by reference here is to allow for the following protocol:
The caller passes in a value indicating how large the array is.
The callee passes out a value indicating how many elements have been populated.
This works well on .net 4, but on earlier versions you would need to use an extra parameter for step 2.
I'm stuck on a seemingly trivial task and need your help.
I need to write a method with the following signature:
System.Array ToIntPtrArray(System.Array a)
where an actual argument can be an array of any pointer type (e.g. int*[], long**[], void*[,]) and returning an array of the same shape with elements of type System.IntPtr having the same numeric values as elements of an input array. The problem is that I do not understand how to extract numeric values of pointers if I do not know their types beforehand.
For example, if I knew beforehand that my argument is always of type void*[], I could write the method as follows:
unsafe IntPtr[] ToIntPtrArray(void*[] a)
{
var result = new IntPtr[a.Length];
for (int i = 0; i < a.Length; i++)
result[i] = (IntPtr) a[i];
return result;
}
But the problem is it could be not void*[], but void**[] or anything else, and the method should be able to handle all cases.
The short answer is, this cannot be done directly. The reasons are that if you pass your conversion function any of the conventional index-capable containers (System.Array, Collections.IList, ArrayList, etc.) performing the index operations will attempt to cast the result to System.Object. Pointers in C# do not derive from Object, so this will result in an SystemNotSupported or similar exception.
There are two reasonable workarounds:
Convert the pointer arrays to void pointer arrays before calling the
method.
Convert the pointer arrays to void pointer pointers before
calling the method.
The first one is rather cumbersome, as it requires duplicating the entire contents of the array with a for loop. The second option requires passing in the length of the array as it is no longer wrapped with a managed System.Array object.
Sample Code
Method:
unsafe Array ToIntPtrArray(void** a, int count)
{
IntPtr[] intPtrArray = new IntPtr[count];
for (int n = 0; n < count; n++)
intPtrArray[n] = new IntPtr(a[n]);
return intPtrArray;
}
Sample Usage (integer pointer array):
int*[] intPtrArray;
// Code that initializes the values of intPtrArray
fixed(int** ptr = &intPtrArray[0])
{
Array result = ToIntPtrArray((void**)ptr, intPtrArray.Length);
}
Sample Usage (void pointer pointer array):
void**[] voidPtrPtrArray;
// Code that initializes the values of voidPtrPtrArray
fixed(void*** ptr = &voidPtrPtrArray[0])
{
Array result = ToIntPtrArray((void**)ptr, voidPtrPtrArray.Length);
}
Sample Usage (multidimensional int pointer array):
int*[,] int2dArray;
// Code that initializes the values of int2dArray
fixed(int** ptr = &int2dArray[0,0])
{
Array result = ToIntPtrArray((void**)ptr, TotalSize(int2dArray));
Array reshaped = ReshapeArray(result,int2dArray);
}
Where TotalSize and ReshapeArray are helper functions that are written to deal with multi-dimensional arrays. For tips on how to accomplish this see: Programatically Declare Array of Arbitrary Rank.
This is a rather difficult problem. Creating an array of the proper shape isn't too bad.
unsafe System.Array ToIntPtrArray(System.Array a)
{
int[] lengths = new int[a.Rank];
int[] lowerBounds = new int[a.Rank];
for (int i = 0; i < a.Rank; ++i)
{
lengths[i] = a.GetLength(i);
lowerBounds[i] = a.GetLowerBound(i);
}
Array newArray = Array.CreateInstance(typeof (IntPtr), lengths, lowerBounds);
// The hard part is iterating over the array.
// Multiplying the lengths will give you the total number of items.
// Then we go from 0 to n-1, and create the indexes
// This loop could be combined with the loop above.
int numItems = 1;
for (int i = 0; i < a.Rank; ++i)
{
numItems *= lengths[i];
}
int[] indexes = new int[a.Rank];
for (int i = 0; i < numItems; ++i)
{
int work = i;
int inc = 1;
for (int r = a.Rank-1; r >= 0; --r)
{
int ix = work%lengths[r];
indexes[r] = lowerBounds[r] + ix;
work -= (ix*inc);
inc *= lengths[r];
}
object obj = a.GetValue(indexes);
// somehow create an IntPtr from a boxed pointer
var myPtr = new IntPtr((long) obj);
newArray.SetValue(myPtr, indexes);
}
return newArray;
}
That creates an array of the right type and shape (dimensions and length), but it has a problem. The GetValue method, which you use to get an item from the array, returns an object. And you can't cast a pointer type to an object. No way, no how. So you can't get the value from the array! If you call GetValue on an array of long*, for example, you'll get "type not supported."
I think you need some way to copy that oddly-shaped array to a one-dimensional array of int* (or any other pointer type). Then you could directly index the temporary array and get the values to populate your IntPtr array.
It's an interesting chicken-and-egg problem. If you pass it as a System.Array, then you can't get items from it because there's no conversion path from object to int* (or any other pointer type). But if you pass it as a pointer type (i.e. int**), then you can't get the shape of the thing.
I suppose you could write it as:
unsafe System.Array ToIntPtrArray(System.Array a, void** aAsPtr)
You then have the System.Array metadata and the actual data in a form that you can use.
Even though the question has been answered well, I feel the need to leave a note/warning to future readers.
The CLR is designed to keep you safe, or at least as safe as possible. It accomplishes this with (among other things) type safety and abstracting memory operations. While you can turn some of these protections off with the unsafe block, some protections are hardcoded into the compiler/runtime. In order to circumvent this additional hurdle, one must resort to some hackey, and possibly slow, code. While these methods work, experience has taught me that doing such things leads to problems down the road, whether it be a change in the runtime, a future programmer needing to modify that segment of code, or you yourself needing to do something else with those pointers later on in the code.
At this point, I would seriously consider a helper dll written in Managed C++ to handle the "raw pointer" side of things. My reasoning is that by using Unsafe, you're already throwing out many protections the CLR offers. You may find it easier to work unencumbered by any additional, baked in protections. Not to mention you can use pointers to their full extent, and then cast them back to intptr when you're done. If nothing else, you may want to look at implementing ToIntPtrArray in C++. Still pass it pointers on the C# side, but escape the CLR's oversight.
Note that I'm not saying that every time you use "unsafe" you should bust out the C++. Quite contrary - unsafe will allow you to do quite a bit - but in this instance, a C++ helper is probably something to consider.
Disclaimer: I have not done a whole lot with managed C++. It could be that I am totally wrong and the CLR would still monitor the pointers. If some more experienced soul could comment and tell me either way, It'd be much appreciated.
I declare a Byte-Array like this:
Byte[] b = new Byte[10];
and assign some values:
for (int i=0; i<b.Length; i++)
{
b[i] = 1;
}
Now I want to zero the array again and call:
b.Initialize();
which doesn't work. The array remains unchanged. Isn't b a value-type array?
See MSDN:
Caution
You can use this method only on value types that have constructors; however, value types that are native to C# do not have constructors.
byte is native.