Избежать потери результата при работе с CUDA и WInForms

Сделал проект на Win Forms, в Visual Studio вторым проектом сделал код на CUDA. Задумка - изображение с формы идет в CUDA, там обрабатывается и возвращается. Но тут пошли сложности - результат функции по идее должен записываться в переменную класса Image, и потом уже по этой переменной рисунок выводиться на форму, но... Visual Studio мне говорит - попытка обращения к защищенной памяти. Понятия не имею как обходить, думал и искал довольно долго. Как-то починить студию, исправить код или что надо, может в машине дело. Позже думаю переписать код чтобы с CUDA передавать обратно только число, не изображение, но заранее опасаюсь, что работать не будет. Код прилагаю ниже.

Первый кусок из самой формы, получаю функцию из библиотеки, потом вызываю и пытаюсь что-нибудь сделать, именно на последней строчке выкидывает ошибку. Если надо будет дополнить важной инфой, то пишите


    HINSTANCE hGetProcIDDLL = LoadLibrary(L"CUDAWin.dll");
    if (!hGetProcIDDLL)
    {
        throw gcnew Exception();
    }
    typedef int(__stdcall* function)(void*);
    function calc = (function)GetProcAddress(hGetProcIDDLL, "calculate");
    if (!calc)
    {
        throw gcnew Exception();
    }
    struct img* image = new img();
    Bitmap^ bitmap = gcnew Bitmap(pct1->Image);
    for (int j = 0; j < image->height; j++)
    {
        for (int i = 0; i < image->width; i++)
        {
            image->image[j * image->width + i] = bitmap -> GetPixel(i,j).ToArgb();
        }
    }
    // Выполняем функцию из DLL библиотеки
    image = (img*)calc((void*)image);
    // Формируем результат для отображения в CLR компоненте
    bitmap = gcnew Bitmap(image->width, image->height);

Отредактировал - не зашел с аккаунта, добавил код передачи, случайно его не вставил

Второй - сама уже функция на CUDA + принимающая, в которой и есть возврат результата.

CUDAWin.cpp

#include<windows.h>
#include "Kernel.cuh"
struct img
{
    int width;
    int height;
    unsigned* image;
};
void* calculate(void* image)
{
    struct img* im = (img*)image;
    if (calc(im->image, im->width, im->height) == -1)
        return NULL;
    return im;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Kernel.cu

__global__ void kernel(unsigned* src, int width,
int height) {
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if ((x < width) && (y < height))
{
    unsigned pixel = src[y * width + x];
    unsigned gray = ((pixel & 0x00FF0000 >> 0x10) +
        (pixel & 0x0000FF00 >> 0x8) + (pixel & 0x000000FF))
        / 3;
    src[y * width + x] = 0xFF000000 | (gray << 0x10) |
        (gray << 0x8) | gray;
}

}

int calc(unsigned* srcImage, int width, int height)
{
    unsigned* dev_srcImage;
    size_t size = sizeof(unsigned) * width * height;
    if (cudaMalloc((void**)&dev_srcImage, size) != cudaError::cudaSuccess) 
        return -1;
    if (cudaMemcpy(dev_srcImage, srcImage, size, cudaMemcpyHostToDevice) != cudaError::cudaSuccess)
        return -1;
    // Максимальное количество нитей на блок может  отличаться
    dim3 threads(128, 128);
    dim3 blocks((width + threads.x - 1) / threads.x, (height + threads.y - 1) / threads.y);
    kernel << <threads, blocks >> > (dev_srcImage, width, height);
    cudaError error = cudaMemcpy(srcImage, dev_srcImage, size, cudaMemcpyDeviceToHost);
    if (error != cudaError::cudaSuccess) return -1;
    cudaFree(dev_srcImage);
    return 0;
}

Ответы (0 шт):