I have a library of c functions I am trying to access from c#. I have tried the PInvoke route but there were structs containing variable length arrays so this approach wasn't working and I was advised to try c++/cli. After looking into it (and asking a lot more questions) I have created a wrapper class for one of my c functions. The input to the c function is a struct that contains two double arrays and the length of one of the arrays (the other being fixed size), as well as a double. I was able to create a little test app (clr console) for my wrapper so I know that its calling the c code and doing what its supposed to, I now just need to figure out how to call it from c#. As its now a managed dll I have added it to my references and I can put it in the code but the method signature has transformed the arrays into pointers whch I cant do in c#. I tried just apssing the arrays, using ref, cant figure out how to make this work.
c++ signature:
static void test_wrapper(double prefix[], double arr[], int arrayLength, double value);
so when I call this in c# its:
Test_Wrapper_Class.test_wrapper(???, ???, array.Length, 2.2);
however the ??? is showing its expecting a double* and I'm not quite sure what to put in for that.
for bonus points I would like to return a double array but not sure about which way to do it. Options for this would be:
just reuse arr as the returned array will be same size
add another double[] in input and fill that one
return a double[]
It is not terribly clear why are making it difficult for the C# to use your function. Keep in mind that the C++/CLI language allows you to either use managed or unmanaged arrays. You are using an unmanaged array as an argument now, so giving the C# code a hard time to call the function. It isn't impossible with unsafe code:
static unsafe void Main(string[] args) { // NOTE unsafe keyword
var arg1 = new double[] { 1, 2, 3 };
var arg2 = new double[] { 4, 5, 6 };
fixed (double* arg1ptr = arg1)
fixed (double* arg2ptr = arg2) {
Test_Wrapper_Class.test_wrapper(arg1ptr, arg2ptr, arg1.Length, 42.0);
}
}
Note how the C# code needs to use the unsafe keyword. And how it is truly unsafe, you didn't include an argument that says how long the 2nd array is so the native code can easily scribble into the GC heap and corrupt it.
But that isn't necessary when you declare the arguments as managed arrays:
static void test_wrapper(array<double>^ prefix, array<double>^ arr, double value);
Safe and easy to call from C#. Note how you no longer need to pass the array length argument, you already know it from prefix->Length. If necessary at all, you can use pin_ptr<> in your C++/CLI code to get a double* that native code can use. Be careful, it is only pinned temporarily.
Related
I'm new to C# from C programming background, sorry for probably a basic question. I'm trying to find the best way to return an array of values from a method.
In C, we can do either of the following:
void myFuction(double[] inputA, int lenA, double* outputA) : the function gets the input array "inputA" of length "lenA" elements, and returns the "outputA" pointer which is allocated memory before the call to "myFunction" and has got populated in the function "myFunction".
double* myFunction (double[] inputA, int lenA) : alternatively, be allocated memory inside "myFucntion" based on a desired length, gets populated, and returned as "return outputA".
What's the best way to do this in C#?
What's the best way to do this in C#?
Pointers are almost never used directly in C#, so the idiomatic signature would use arrays:
double[] myFunction (double[] inputA, int lenA)
but note that in C# you can also get the length of an array very easily (int len = inputA.Length), so lenA may not be needed unless you want to support processing a subset of the array.
As you progress, you'll find that other data structures like List and interfaces like IEnumerable may be preferable depending on your use case (i.e. you may decide that the function should just return an iterable collection without specifying the actual type of that collection).
As a side note (and from someone who went from C++ to C# myself), the best thing you can do is NOT think of C# as an "extension" or "alternative" to C++. While the syntax and types are very similar, C# as a managed language does many fundamental things very differently, so you may be limiting yourself if you just try to "port" C++ code to C#. Try to think of it as a brand new language and framework with some syntax overlap.
c# allows for both of these methods as well, however arrays are denoted with [] even in returns instead of the * pointer.
double[] myFunction(double[] inputA, int lenA)
{
double[] output = new double[lengthOfArray];
...
return output;
}
Alternatively, c# allows for an "out" parameter that can be used in a similar manner.
void myFunction(double[] inputA, int lenA, out double[] output)
{
...
output = ...
//OR
output[0] = 1; //replace 0 with index #
}
Both are acceptable practices, with the first example being the more common way to do it in c# for readable and organization.
I have to wrap the following c++ function:
class Foo {
unsigned int *getVector3();
};
The member function getVector3, returns a (fixed) 3D array, eg [1,2,3]. How should I use arrays_csharp.i for a return type ? The documentation only describes for input parameters:
22.4 C# Arrays
In my case the return type is always a fixed size array (of 3 elements).
I have an answer, although it's not entirely satisfactory in my view. That's mostly limited by my knowledge of C# though, so you can probably make it work better than I can.
I don't think arrays_csharp is what you're looking for here. It seems to be about pinning memory so it can be used as input to a function, but in your scenario you've got memory already allocated that you'd like to work with.
That's fairly easy (and for a 3D vector pretty cheap), using System.InteropServices.Marshal normally. So I put together a few typemaps using that which does what you want:
%module test
%typemap(csout,excode=SWIGEXCODE) unsigned *getVector {
global::System.IntPtr cPtr = $imcall;$excode
int[] tmp = new int[3];
// I have no idea why Marshal.Copy does not seem to have any support for unsigned types...
global::System.Runtime.InteropServices.Marshal.Copy(cPtr, tmp, 0, 3);
// There is probably a better way to go from int[3] -> uint[3], but it is not obvious to me
return new $typemap(cstype, $*1_type)[3]{($typemap(cstype, $*1_type))tmp[0],($typemap(cstype, $*1_type))tmp[1],($typemap(cstype, $*1_type))tmp[2]};
}
%typemap(cstype) unsigned *getVector "$typemap(cstype, $*1_type)[]"
%inline %{
unsigned *getVector() {
static unsigned arr[3] = {1,2,3};
return arr;
}
%}
A few notes though:
$typemap(cstype, $*1_type) is a fancy way of saying find me the C# type corresponding to my C element type. I tend to try and avoid explicitly writing types in typemaps as it makes things more generic.
Having said that Marshal.Copy only seems to work with signed rather than unsigned array types, for reasons I can't quite figure out. And I can't see an automatic way to find the corresponding signed type for an unsigned one, so I did have to explicitly write int[]
I'm not sure that signed -> unsigned casting is actually well defined behaviour in C#. Maybe this won't work properly for values where the last bit is set. You can work around that by increasing the size of the int type for tmp. (E.g. use int64 instead of int32, but that's not pretty)
There ought to be a better way to cast a whole array than what I've done, but I don't know the C# language all that well.
That said this is sufficient that I can run the following program (with Mono) and get the output expected
public class runme {
static void Main(string[] args) {
uint[] arr = test.getVector();
System.Console.WriteLine(arr[0]);
System.Console.WriteLine(arr[1]);
System.Console.WriteLine(arr[2]);
}
}
We could do a bunch more work to make this generic (i.e. other size vectors, other datatypes int16[4], etc.) if that was useful.
I'm learning C++ and it seems like it is impossible to have an array as a return type. Is this true?
int foo(){}
works fine but
int[] foo(){}
does not. What is the commonly accepted work around to this?
I'm currently working on a project that utilizes both C# and C++. I have a C# file that access some DLL code with:
[DllImport("Test.dll")]
public static extern byte[,] getBytes(
[In] string filePath,
[In] string dataGroup);
My header file has:
TEST_DLL BYTE[][] getBytes(std::string filePath, std::string dataGroup);
/* This throws an error since I can't use an array as a return type. */
and my implementation inside the .cpp file is:
TEST_DLL BYTE[][] getBytes(std::string filePath, std::string dataGroup)
{
printf("getBytes entered."
/* More code here...*/
}
/* This also throws an error due to the array use. */
Basically, I'm trying to return a 2D byte array from my DLL code without needing to convert anything on the C# side, i.e., all code execution related to getBytes should occur in the C++ code.
I have a working example of this that does not use an array but rather a void*, which from my understanding is a pointer to the array I'm returning. I then have a C# function that uses an IntPtr and Marshal.Copy to get the byte array. I'm trying to determine the overhead difference between the two methods. I would imagine that it would be much faster to return a 2D byte array directly from the C++ code instead of using the additional C# conversion code (the datasets I'm using are huge - some over 500GB so every little bit of optimization counts).
Basically, how can I retrieve a 2D byte array purely from my C++ code without having to convert it in C#?
You have two separate issues:
Returning an array from a C/C++ function (method)
Interoperating with C#.
There are a number of solutions to issue #1. Probably the best is to return a vector (if you want to copy the data out) or a reference to a vector (if you have a return value that will stay around "forever")) You could also pass in a reference to a vector as a parameter and populate the vector in your function.
Issue #2: A C# array is NOT a native data type in C++, so you will need special purpose code to "marshal" the data into the appropriate C# type. See this question for more details.
Consider the following stucture in c++, I need to wrap this using CLI to make it usable for C#
typedef struct A
{
int b[5];
A* next;
};
How can I do so? Please help.
non-op edit:
What I've tried is the following:
public ref struct ANET
{
array<int>^ b;
ANET^ next;
ANET()
{ b = gcnew array<int>(5) }
};
now let's say we have an pointer of object of A is a, pointer of object ofANET is aNET
nSize = sizeof(a->b)/sizeof(a->b[0]);
Marshal::Copy( IntPtr( ( void * ) a->b ), aNET->b, 0, nSize);
so far I am able get the values of a->b in aNET->b but I am stuck with marshaling the pointer of a->next to aNET->next.
Thanks
That's a linked list. So one option is to write C++/CLI code to adapt the native linked list to a .net LinkedList<T>. Going down this route will mean that you need to make copies of the list whenever it is modified in the native code and needs to be returned to the managed code. And vice versa.
If making copies is not an option then you should wrap the native linked list in a managed class. So you don't try to convert the struct definition at all. Instead you write a C++/CLI managed class that encapsulates the functionality that you need to expose. I can't say much more than that because you haven't given any information on the operations that you need to perform on this list. Now have you explained what the data flow is.
I have a Blah.cs:
public unsafe static int Main()
{
int[] ai = {1, 2, 3, 4, 5};
UIntPtr stai = (UIntPtr) ai.Length;
CManagedStuff obj = new CManagedStuff();
obj.DoSomething(ai, stai);
}
Then a ManagedStuff.cpp:
void CManagedStuff::DoSomething(int^ _ai, UIntPtr _stai)
{
// Here I should do something to marshal the int^ to an int*
pUnmanagedStuff->DoSomething(_ai, (size_t) _stai);
}
And an UnmanagedStuff.cpp:
void CUnmanagedStuff::DoSomething(int* _ai, size_t _stai)
{
// Walk and print the _stai ints in _ai
}
How can I pass int[] ai from Main to ManagedStuff::DoSomething? I understand there is no marshaling in that call, because all the code involved is managed.
And how can I then marshal int^ _ai in ManagedStuff::DoSomething to call UnmanagedStuff::DoSomething? If I had an int[] _ai the code in the answer for this SO question may help (C#: Marshalling a "pointer to an int array" from a SendMessage() lParam).
Alternatively, how can I avoid working with C#, C++ interop, Microsoft and Windows, and stop world suffering?
I just need to point out how broken the original idea is.
In native code, you can pass an array by passing the address of the first element, because adjacent elements can be found through pointer arithmetic.
In managed code, the elements are also stored adjacently, but passing a int^ boxes the element, making a copy outside the array. This copy will not have any other array elements stored nearby.
In fact, this also happens in native cross-process communications. The trick of using pointer arithmetic to find other elements only works in-process, and is not generally applicable.
OK, I've got it working like this:
void CManagedStuff::DoSomething(array<int>^ _ai, UIntPtr _stai)
{
// Here I should do something to marshal the int^ to an int*
pin_ptr<int> _aiPinned = &_ai[0];
pUnmanagedStuff->DoSomething(_aiPinned, (size_t) _stai);
}
First, passing an array<int>^.
Secondly, as Tamschi was suggesting, using a pin pointer pointing to the address of the first element in the array.
You have to pin the managed resource (your array), so the garbage collector doesn't move it while you're using the pointer.
In C#, you can do this with the fixed statement: fixed Statement (C# Reference)
Pinning in C++ works with pinning pointers, which pin a managed object while they're in scope. (A pointer to any element will pin the entire array):
// In CManagedStuff:
pin_ptr<int> _aiPinned = _ai
More info: C++/CLI in Action - Using interior and pinning pointers