using c++11 inside a c# program - c#

I am programming some graphical filters in my main program which is based upon C#.
However C# is not fast for getpixel / putpixel.
I've seen workarounds for it, using unsafe code in C#
Unsafe code gives me a bit an unsafe feeling too, as i understand the benefit of safe code and memory cleanup.
So now i am wondering....
Might it be better to write this unsafe code in a separated dll based on C++ ?.
However I never made mixed language programs, so i am wondered.
How would one pass a bitmap from C# to a function in a C++
i can set the reference to the dll, but i dont think that will be enough
How would one pass some returned values and the bitmap back again to the c# main program
Also what if i used another compiler to write the c++11 .dll would that be a problem?
The main program is written in visual studio 2010 expres

Actually I am doing exactly the same you mentioned (graphical filters) using CUDA. To be able to call C functions from managed code (WinForms) I utilize InteropServices.
Let's say you have 2 projects in a solution - C++ library and some C# project.
To declare function in C++ library I use following parameters:
extern "C" int __declspec(dllexport) __stdcall cudaCopyInputData
(int n, int w, int h, byte* data)
{
inputBuffer = data;
bufferLength = n;
inputWidth = w;
inputHeight = h;
useFloatBuffer = 0;
binaryBufferValid = 0;
int bufferSize = bufferLength * sizeof(byte);
int floatBufferSize = bufferLength * sizeof(float);
int binaryBufferSize = w * h * sizeof(int);
cudaMalloc((void**)&cudaInputBuffer, bufferSize);
cudaMemcpy(cudaInputBuffer, inputBuffer, bufferSize, cudaMemcpyHostToDevice);
cudaMalloc((void**)&cudaFloatBuffer, floatBufferSize);
cudaMalloc((void**)&cudaBinaryBuffer, binaryBufferSize);
return 0;
}
To be able to use it from C# project I import this function as a static method using InteropServices:
[DllImport("CUDA Dll.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int cudaCopyInputData(int n, int w, int h, IntPtr data);
You are then able to use it from managed code as a standard method.
To pass Bitmap data to the imported method you can use something like this:
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
Then pass bmpData.Scan0 as a pointer to bitmap data and some other parameters like Width, Height, Stride or whatever you want to figure out data format in the C function. In the example above you will have 4 bytes for every pixel (3 bytes + 1 dummy byte) so it's comfortable to process it.
To reuse processed data from your bmp object you just call after processing it:
bmp.UnlockBits(bmpData);

If you use C++ then you also can use C# with unsafe code. Both is unsafe and in C# you still don't need to care about memory cleanup. The only thing you have to care about is accessing invalid pointers which will cause a AccessViolationException.
public unsafe void SwapChannels(Byte[] imageSrc)
{
fixed (Byte* pImageSrc = imageSrc)
{
// Swap channels here
}
}
I'm using unsafe code in my image libraries too. If you are not going cross-plattform you can also use C++/CLI.

There are a few ways to do interop between C++ and C#: C++/CLI, COM and P/Invoke.
C++/CLI and COM have areas in which either one can be better, but I don't think P/Invoke should ever be used, except for some quick-and-dirty solutions.
In your case, especially since you mention that the C++ DLL is built with another compiler, I think COM is your best bet.
But note that using C++ is pretty much like using unsafe code in C#. Pointers all around, for example.

SWIG allows you to easily wrap C++ code and expose classes/functions in c#. I used it to expose some of my image processing routines in c# and it's a breeze.You end up with classes behaving as c# classes , the SWIG generated wrappers handle the type conversions (mostly) and the P/Invoke stuff.
The site swig.org is down at the moment i'm writing, if somebody knows why ,please comment
As for the compiler mixup I have good experience with Mingw compiled DLL.
edit: You still can access the project sourceforge page

Related

Most efficient way to pass data from C++ to C#

I am looking for the best way to transfer a large amount of data from C++ (struct or a value class?) into a C# class doing as little data copying as possible. In the sample code below, I have a vector of SubClass objects that has the potential to be very large (10+ million). So I want to avoid a data copy if possible.
Should I/can I just allocate the objects in GC first and use them directly in c++ and forget about the native c++ structures? (Performance is my concern with this one.)
Or, is there some trick that I leverage what is allocated in C++ without causing a data copy?
Here is a sample of something along the lines of what I want to use as a transfer between managed and unmanaged code.
#include <string>
#include <vector>
struct SubClass {
std::string DataItem1;
// lots more here
std::string DataItem50;
};
struct Sample {
int IntValue;
std::string StringValue;
std::vector<std::string> SmallList;
std::vector<SubClass> HugeList;
};
If I can avoid getting into the weeds with pinvoke and COM classes, I would prefer it.
Following the example from Unity (who uses C#), Native plugin example uses a GC handle to transfer data from C# to C++. We can try the opposite to send data to C++ from C#.
Pin down a C# variable to allow faster copying.
using System;
using System.Collections;
using System.Runtime.InteropServices;
// vertices is a Vector3[], where Vector3 is a struct
// of 3 floats using a sequential layout attribute
void test(){
GCHandle gcVertices = GCHandle.Alloc (vertices, GCHandleType.Pinned);
}
Transfer the handle to C++ using marshaling. It's unavoidable that you have to copy something. Here copying a pointer should be good enough. More on marshaling according to Microsoft doc.
[DllImport("your dll")]
private static extern void SendHandle(IntPtr vertexHandle, int vertexCount);
SendHandle(gcVertices, vertices.Length);
Inside C++, you'll receive the handle as a pointer type to a C++ type of your choosing. In this case, vertices are a list of structs of 3 floats. The reference code decided to use float *. You just need to do pointer arithmetic properly depending on the pointed type, including the case of void *.
extern "C" __decl(dllexport) void SendHandle(float* vertices, int vertexCount);
Here the example code copies data directly from the pointer, but you can also write to the pointer's location.
for (int i = 0 ; i < vertexCount; i++)
{
// read from C# heap
float x = vertices[0];
float y = vertices[1];
float z = vertices[2];
// write to C# heap
*vertices = sqrt(x);
*(vertices + 1) = sqrt(y);
*(vertices + 2) = sqrt(z);
vertices += 3; // because it is a list of struct of 3 floats
}
Clean up the pinned handle from the C# side to resume the garbage collector.
gcVertices.Free();
As for strings, I believe the interop library has an implementation that handles pointer arithmetic and copying for you. You could probably just use a string type directly inside the exposed export function, as long as you specify how to marshal it with the MarshalAs attribute in C# and a library in C++ if you are not converting to the C type char *.

P/Invoke with arrays of double - marshalling data between C# and C++

I've read the various MSDN pages on C++ Interop with P/Invoke here and here but I am still confused.
I have some large arrays of doubles that I need to get into native code, and some resulting arrays that need to get back. I do not know the sizes of the output arrays in advance. For simplicity, I will use only a single array in the example. The platform is x64; I read that marshalling internals are quite different between 32- and 64-bit environments so this might be important.
C#
[DllImport("NativeLib.dll")]
public static extern void ComputeSomething(double[] inputs, int inlen,
[Out] out IntPtr outputs, [Out] out int outlen);
[DllImport("NativeLib.dll")]
public static extern void FreeArray(IntPtr outputs);
public void Compute(double[] inputs, out double[] outputs)
{
IntPtr output_ptr;
int outlen;
ComputeSomething(inputs, inputs.Length, out output_ptr, out outlen);
outputs = new double[outlen];
Marshal.Copy(output_ptr, outputs, 0, outlen);
FreeArray(output_ptr);
}
C++
extern "C"
{
void ComputeSomething(double* inputs, int input_length,
double** outputs, int* output_length)
{
//...
*output_length = ...;
*outputs = new double[output_length];
//...
}
void FreeArray(double* outputs)
{
delete[] outputs;
}
}
It works, that is, I can read out the doubles I wrote into the array on the C++ side. However, I wonder:
Is this really the right way to use P/Invoke?
Aren't my signatures needlessly complicated?
Can P/Invoke be used more efficiently to solve this problem?
I believe I read that marshalling for single dimensional arrays of built-in types can be avoided. Is there a way around Marshal.Copy?
Note that we have a working C++/Cli version, but there are some problems related to local statics in third-party library code that lead to crashes. Microsoft marked this issue as WONTFIX, which is why I am looking for alternatives.
It is okayish. The complete lack of a way to return an error code is pretty bad, that's going to hurt when the arrays are large and the program runs out of memory. The hard crash you get is pretty undiagnosable.
The need to copy the arrays and to explicitly release them doesn't win any prizes of course. You solve that by letting the caller pass a pointer to its own array and you just write the elements. You however need a protocol to let the caller figure out how large the array needs to be, that is going to require calling the method twice. The first call returns the required size, the second call gets the job done.
A boilerplate example would be:
[DllImport("foo.dll")]
private static int ReturnData(double[] data, ref int dataLength);
And a sample usage:
int len = 0;
double[] data = null;
int err = ReturnData(data, ref len);
if (err == ERROR_MORE_DATA) { // NOTE: expected
data = new double[len];
err = ReturnData(data, len);
}
No need to copy, no need to release memory, good thing. The native code can corrupt the GC heap if it doesn't pay attention to the passed len, not such a good thing. But of course easy to avoid.
If it were practical to separate the code that determines the output length from the code that populates the output then you could:
Export a function that returned the output length.
Call that from the C# code and then allocate the output buffer.
Call the unmanaged code again, this time asking it to populate the output buffer.
But I'm assuming that you have rejected this option because it is impractical. In which case your code is a perfectly reasonable way to solve your problem. In fact I would say that you've done a very good job.
The code will work just the same in x86 once you fix the calling convention mismatch. On the C++ side the calling convention is cdecl, but on the C# side it is stdcall. That doesn't matter on x64 since there is only one calling convention. But it would be a problem under x86.
Some comments:
You don't need to use [Out] as well as out. The latter implies the former.
You can avoid exporting the deallocator by allocating off a shared heap. For instance CoTaskMemAlloc on the C++ side, and then deallocate with Mashal.FreeCoTaskMem on the C# side.
If you knew the array size beforehand, you could write a C++/CLI DLL that takes the managed array as parameter, pins it, and calls the native C++ DLL on the pinned pointer it obtains.
But if it's output-only, I don't see any version without a copy. You can use a SAFEARRAY so P/Invoke does the copying instead of you, but that's all.

Calling C++ Library from C# with C++/CLI Wrapper

I have a C++ library, header of which looks like:
void NotMyFun(double * a, int * b);
The function reads from a, and writes to b. To call the library I have created a C++/CLI wrapper, where below function is defined:
static void MyWrapperFun(double * a, int * b)
{
NotMyFun(a,b);
}
and works OK. From C# code, say, I have two managed arrays, i.e. double[] ma and double[] mb, where ma already holds some meaningful data, and mb is -meaningfully- filled when wrapper is called. Is below an OK way to call the wrapper function?
unsafe
{
fixed (double* pma = ma)
{
fixed (int* pmb = mb)
{
MyWrapperNS.MyWrapperClass.MyWrapperFun(pma,pmb);
}
}
}
Are the unsafe pointers a fast way? Is any data copying involved here while passing and retrieving to/from C++/CLI wrapper? Or pointers are already pointing to a continuous memory space in C# arrays?
Besides, do I need any manual memory cleaning here? If the pointers are tied to the memory of managed C# arrays, I guess they are properly garbage collected after, but just want to be sure.
Personally I think you are over-complicating things. I'd avoid the unsafe code and skip the C++/CLI layer. I'd use a simple p/invoke declared like this:
[DllImport(#"mylib.dll")]
static extern void NotMyFun(double[] a, int[] b);
Because double and int are blittable types, no copying is necessary. The marshaller just pins the arrays for the duration of the call.

How to pass an image using PInvoke

I have a C DLL which does some processing on an image and returns the result. So I am trying to pass an image over from the .NET side, but right now I am stuck, and I'm not sure whether that's on the types, the intricacies of marshaling, or syntax. Since I am a noob it could be all three.
I can call other functions in the DLL in question, so at least some of the foundations are in place. For example, when I call:
IntPtr versionIntPtr = GetDLLVersionNumber();
string version = Marshal.PtrToStringAnsi(versionIntPtr);
Console.WriteLine("DLL version number reported as: " + version);
and this works absolutely fine, printing the current version of the DLL to the console.
When I look at C code sample which uses the same function, it appears to use the function as follows:
unsigned char* ExtractImageInfo(const char* pixels, size_t width, size_t height)
(I also have a header file where the same function is mentioned as follows:
... ExtractImageInformation(struct ImageData image, void* imageInformation);
but I don't really know what this means.)
So my attempt to use this function goes as follows:
First I specify the interface to the DLL:
[DllImport("C:\\MyDLL", EntryPoint = "ExtractImageInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ExtractImageInfo(IntPtr image, UInt32 imageWidth, UInt32 imageHeight);
Then, I get an image of the right type and get its dimensions:
Bitmap bitmap1 = (Bitmap)Image.FromFile("C:\\Images\\myImage.bmp");
UInt32 _imageWidth = Convert.ToUInt32(bitmap1.Width);
UInt32 _imageHeight = Convert.ToUInt32(bitmap1.Height);
Then I get a pointer to the image (since I think that's what I need to pass):
IntPtr bitmap1Ptr = bitmap1.GetHbitmap();
And then I call the function...
IntPtr myProcessedImage;
myProcessedImage = ExtractImageInfo(bitmap1Ptr, _imageWidth, _imageHeight);
But it doesn't work - I don't get back a pointer to my processed data. A big part of what I'm wondering here is whether I am passing the image in the right way, and whether the syntax for my interface to the native function is right. I think probably the answer to both could be NO!
I've only had a few days of reading and experimenting with PInvoke, so if anyone can point out to me the error of my ways I will be eternally grateful :-)
unsigned char* ExtractImageInfo(const char* pixels, size_t width, size_t height)
The name of the argument strongly suggests it wants a pointer to the raw pixel data. You can get one from Bitmap.LockBits(), BitmapData.Scan0 property. Don't call UnlockBits() until the function returns.
The return type of the function is a significant memory management problem. Whatever buffer pointer is returned is almost certainly going to have to be released. You cannot do so from managed code, you don't have access to the allocator used by this C code to call the proper version of free(). Call this function a million times and double-check that you don't have an out-of-control memory leak. If you do then you can't pinvoke it, a C++/CLI wrapper is required although the odds that it works correctly are fairly slim as well. This is a poorly designed function that's hard to use from any code, including C.

How can I copy unmanaged data in C# and how fast is it?

I have two unmanaged pointers in the form of IntPtr and want to copy data between them. How can I do this? I know the method Marshal.Copy, but it can only copy between unmanaged and managed.
And the second part: Is copying unmanaged data from C# slower than doing it in unmanaged C/C++ using memcpy?
Edit: I would be especially interested in a platform independet implementation.
You can use the win32 memcpy function via P-Invoke.
[DllImport("msvcrt.dll", SetLastError = false)]
static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count);
Apart from the (slight) overhead calling a win32 function from managed code, the actual copy performance should be the same as C/C++ code that uses the same function.
Don't forget that you can also use an unsafe block (and compiler option) and simply copy the data one byte/int/long at a time:
unsafe
{
// srcPtr and destPtr are IntPtr's pointing to valid memory locations
// size is the number of long (normally 4 bytes) to copy
long* src = (long*)srcPtr;
long* dest = (long*)destPtr;
for (int i = 0; i < size / sizeof(long); i++)
{
dest[i] = src[i];
}
}
This removes the platform dependency, but you need to be very careful with the bounds checking and pointer arithmetic.
Try System.Buffer.MemoryCopy, see the bottom of the page for supported target frameworks.
I believe that the main difference between this and the other solutions that use P/Invoke is that this method avoids the P/Invoke for smaller sizes and just does the copying directly.
Here's the guts of the implementation in .NET Core (latest as of 2020-09-04).
Without making comments on performance, purely because I have not tested it. You can achieve the same performance as unmanaged copy by using either CopyMemory or MoveMemory from Kernel32 via interop.
Here is the declaration for CopyMemory
[DllImport("kernel32.dll")]
static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
You could look at System.Runtime.CompilerServices.Unsafe.CopyBlock
It seems to allow you to copy bytes from the source address (designated by a void*) to the destination address (designated by a void*).
It also overriden to support ref byte as the source and destination.
[edit]
Disappointingly it appears not to be implemented in Mono
[edit] For those who are interested in this and using Unity, you should instead look to Unity's UnsafeUtility.MemCpy
CopyMemory aka RtlCopyMemory aka memcpy() will be just as fast whether called from C# or C (other than the tiny overhead of PInvoking the method itself).
Something to keep in mind, though, is that CopyMemory should only be used when you're sure that the source and destination ranges do not overlap. If they do overlap, you need to use MoveMemory instead, which will be slower.
Here is a declaration for CopyMeSomeMemory, showing how many different ways you can do the same thing in .Net:
[DllImport("kernel32.dll", EntryPoint = "RtlCopyMemory")]
public static extern void CopyMeSomeMemory(IntPtr Destination,
IntPtr Source, uint Length);
For the record, I think Buffer.BlockCopy in .Net just wraps one of these functions, too.

Categories

Resources