简体   繁体   English

从C#将数据传入和传出DLL

[英]Passing Data in and out of a DLL from C#

I am attempting to create a C# program that can pass data into a C/C++ DLL, store the data, and complete calculations on it. 我正在尝试创建一个C#程序,该程序可以将数据传递到C / C ++ DLL中,存储数据并完成对它的计算。 The result would then be returned to the C# program. 然后将结果返回到C#程序。 The reason for not using C# for the calculations is that I am planning to accelerate it with CUDA. 不使用C#进行计算的原因是我计划使用CUDA加速它。

I currently declaring a byte array in C#, and passing that as an argument to the DLL to send data. 我目前在C#中声明一个字节数组,并将其作为参数传递给DLL以发送数据。

I then declare a byte array of the same size in C# and pass it as an argument to receive the data. 然后,我在C#中声明一个大小相同的字节数组,并将其作为参数传递以接收数据。 The DLL should then write the results into that memory. DLL然后应将结果写入该内存。

When I run the program, the correct numbers get printed to the screen. 当我运行程序时,正确的数字会显示在屏幕上。 (As I am writing 1,2,3... to the array twice, the addition of these is 2,4,6...) "The cat chased the mouse" is then printed. (当我将1,2,3 ...两次写入数组时,它们的加法是2,4,6...。)然后打印“猫追了老鼠”。 When I press a key, "The mouse chased the cat" is displayed, and the program crashes before it exits displaying a vshost32.exe stopped working error. 当我按一个键时,将显示“鼠标追逐了猫”,并且该程序在退出前崩溃,并显示vshost32.exe停止工作错误。 I was able to solve this error from this question . 我能够从这个问题解决这个错误。

Now when I attempt to run the EXE directly from windows explorer, I get the number 36 printed as the first step, but then I get the following error on the compute function call: 现在,当我尝试直接从Windows资源管理器运行EXE时,第一步得到的数字为36,但是在计算函数调用时出现以下错误:

"Unhanded exception: System.AccessViolationException Attempted to read or write protected memory. This is often an indication that other memory is corrupt" “未处理的异常:System.AccessViolationException尝试读取或写入受保护的内存。这通常表明其他内存已损坏”

I know the DLL loaded correctly because the init function returned the correct number. 我知道DLL已正确加载,因为init函数返回了正确的数字。 I am not sure why it would only be crashing when I am running it as an EXE and not in the debugger. 我不确定为什么仅当我将其作为EXE而不是在调试器中运行时才会崩溃。 What could be causing this? 是什么原因造成的?

Is there a different way I should be handling the memory exchange between the DLL and the C# program? 我应该以其他方式处理DLL和C#程序之间的内存交换吗? My goal is to avoid copying it using a Marshal Copy as I need this to be high performance. 我的目标是避免使用元帅副本来复制它,因为我需要这样做才能提高性能。 The end goal would be the DLL copying the memory to or from the GPU and the GPU doing the calculations, so I see no reason to have it copied a 2nd time in the DLL before going to the GPU. 最终目标是DLL将内存复制到GPU或从GPU复制内存,然后GPU进行计算,因此我认为没有理由在进入GPU之前将其第二次复制到DLL中。

C++ DLL Code (written as C code) C ++ DLL代码(编写为C代码)

#include "stdafx.h"  
#include "stdlib.h"
const int CONSTANT = 3;
char** items;
int itemCount = 0;
int xcnt = -1;
int ycnt = -1;

extern "C" int __declspec(dllexport) __stdcall init(int itemcount_local, int xcnt_local, int ycnt_local){
    itemCount = itemcount_local;
    xcnt = xcnt_local;
    ycnt = ycnt_local;
    items = (char**)malloc(itemCount);
    if (items == NULL){
        return -1;
    }
    for (int i = 0; i < itemCount; i++){
        items[i] = (char*)malloc(CONSTANT*xcnt*ycnt);
        if (items[i] == NULL){
            return -1;
        }
        for (int d = 0; d < CONSTANT*xcnt*ycnt; d++){
            items[i][d] = 0;
        }
    }
    return CONSTANT*xcnt*ycnt;
}

//frees the memory created in init
extern "C" void __declspec(dllexport) __stdcall cleanup(){
    for (int i = 0; i < itemCount; i++){
        free(items[i]);
    }
    free(items);
    return;
}

extern "C" void __declspec(dllexport) __stdcall loadItem(int index, char* data){
    memcpy(items[index], data, CONSTANT*xcnt*ycnt);
    return;
}

//fills the buffer with the computed result.  Buffer needs to be the size of CONSTANT*xcnt*ycnt
extern "C" void __declspec(dllexport) __stdcall compute(char* buffer){
    for (int x = 0; x < CONSTANT*xcnt*ycnt; x++){
        int sum = 0;
        for (int i = 0; i < itemCount; i++){
            sum += items[i][x];
        }
        if (sum > 255){ //saturate at 255
            buffer[x] = 255;
        }
        else {
            buffer[x] = sum;
        }
    }
    return;
}

C# code C#代码

class Program
{
[DllImport("DllTest1.dll", CallingConvention=CallingConvention.StdCall, SetLastError = true, CharSet = CharSet.Ansi)]
public static extern int  init(int imagecount_local, int xres_local, int yres_local);

[DllImport("DllTest1.dll", CallingConvention=CallingConvention.StdCall, SetLastError = true, CharSet = CharSet.Ansi)]
public static extern void cleanup();

[DllImport("DllTest1.dll", CallingConvention=CallingConvention.StdCall, SetLastError = true, CharSet = CharSet.Ansi)]
public static extern void loadItem(int index, byte[] data);

[DllImport("DllTest1.dll", CallingConvention=CallingConvention.StdCall, SetLastError = true, CharSet = CharSet.Ansi)]
public static extern void compute(byte[] buffer);

static void Main(string[] args)
{

    int x = 4, y = 3;
    int total = x * y * 3;
    Console.WriteLine(init(5, x, y));

    byte[] a = new byte[total];

    compute(a);
    for (int i = 0; i < total; i++)
    {
        Console.WriteLine(a[i]);
    }

    byte[] b = new byte[total];
    for (int i = 0; i < total; i++)
    {
        b[i] = (byte)i;
    }
    loadItem(0, b);
    loadItem(1, b);

    compute(a);
    for (int i = 0; i < total; i++)
    {
        Console.WriteLine(a[i]);
    }

    //cleanup();
    Console.WriteLine("The cat chased the mouse");
    Console.ReadKey();
    Console.WriteLine("The mouse chased the cat");
    return;
}
}

I was able to solve the problem. 我能够解决问题。 The line 线

items = (char**)malloc(itemCount);

should have been 本来应该

items = (char**)malloc(itemCount*sizeof(char*));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM