Reputation: 2180
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.
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
Upvotes: 1
Views: 300
Reputation: 1558
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);
Upvotes: 4
Reputation: 6281
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.
Upvotes: 1
Reputation: 6678
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.
Upvotes: 1
Reputation: 1201
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
Upvotes: 0