Question

What I am trying to do is write a C# application to generate pictures of fractals (mandlebrot and julia sets). I am using unmanaged C++ with CUDA to do the heavy lifting, and C# for the user interface. When I try to run this code, I am not able to call the method I wrote in the DLL - I get an unhandled exception error for an invalid parameter.

The C++ DLL is designed to return a pointer to the pixel data for a bitmap, which is used by the .NET Bitmap to create a bitmap and display it in a PictureBox control.

Here is the relevant code:

C++: (CUDA methods omitted for conciseness

extern "C" __declspec(dllexport) int* generateBitmap(int width, int height)
{
int *bmpData = (int*)malloc(3*width*height*sizeof(int));
int *dev_bmp;

gpuErrchk(cudaMalloc((void**)&dev_bmp, (3*width*height*sizeof(int))));

kernel<<<BLOCKS_PER_GRID, THREADS_PER_BLOCK>>>(dev_bmp, width, height);
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());

cudaFree(dev_bmp);
return bmpData;
}

C#:

public class NativeMethods
{
    [DllImport(@"C:\...\FractalMaxUnmanaged.dll")]
    public static unsafe extern int* generateBitmap(int width, int height);
}

//...

private unsafe void mandlebrotButton_Click(object sender, EventArgs e)
{
    int* ptr = NativeMethods.generateBitmap(FractalBox1.Width, FractalBox1.Height);
    IntPtr iptr = new IntPtr(ptr)

    fractalBitmap = new Bitmap(
                        FractalBox1.Width,
                        FractalBox1.Height,
                        3,
                        System.Drawing.Imaging.PixelFormat.Format24bppRgb,
                        iptr );

     FractalBox1.Image = fractalBitmap;
}

Error:

************** Exception Text **************
Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\...WindowsFormsApplication1.vshost.exe'.

I believe the problem I am having is with the IntPtr - is this the correct method to pass a pointer from unmanaged C++ to a C# application? Is there a better method? Is passing a pointer the best method to accomplish what I am trying to do or is there a better way to pass the pixel data from unmanaged C++ w/ CUDA to C#?

EDIT:

From what I gather from the error I get when I debug the application, PInvokeStackImbalance implies that the signatures for the unmanaged and managed code don't match. However, they sure look like they match to me.

I feel like I'm missing something obvious here, any help or recommended reading would be appreciated.

Était-ce utile?

La solution

You need to define the same calling convention in C and C#: In C:

extern "C" __declspec(dllexport) int* __cdecl generateBitmap(int width, int height)

In C#:

[DllImport(@"C:\...\FractalMaxUnmanaged.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr generateBitmap(int width, int height);

Instead of cdecl you can also use stdcall, it only needs to be the same on both sides. And handling my self a lot of managed/unmanaged code, I also advise you to pass the image array as an argument and do the memory allocation in C#. Doing so, you don't need to take care of manually freeing memory in managed world.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top