1

我正在基于 C# 的主程序中编写一些图形过滤器。
但是 C# 对于 getpixel / putpixel 并不快。
我已经看到了解决方法,在 C#
不安全代码中使用不安全代码也给我一种不安全的感觉,因为我了解安全代码和内存清理的好处。

所以现在我想知道....
在基于 C++ 的单独 dll 中编写这个不安全的代码会更好吗?
但是我从未制作过混合语言程序,所以我很想知道。

  • 如何将位图从 C# 传递到 C++ 中的函数我可以设置对 dll 的引用,但我认为这还不够
  • 如何将一些返回值和位图再次传递回 c# 主程序

另外,如果我使用另一个编译器编写 c++11 .dll 会不会有问题?主程序用visual studio 2010 expres编写

4

4 回答 4

4

实际上,我正在使用 CUDA 做与您提到的(图形过滤器)完全相同的操作。为了能够从托管代码 (WinForms) 调用 C 函数,我使用了 InteropServices。

假设您在一个解决方案中有 2 个项目 - C++ 库和一些 C# 项目。

要在 C++ 库中声明函数,我使用以下参数:

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;
}

为了能够从 C# 项目中使用它,我使用 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);

然后,您可以从托管代码中将其用作标准方法。

要将位图数据传递给导入的方法,您可以使用如下内容:

BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

然后将 bmpData.Scan0 作为指向位图数据的指针和一些其他参数(如 Width、Height、Stride 或任何您想在 C 函数中确定数据格式的参数)传递。在上面的示例中,每个像素将有 4 个字节(3 个字节 + 1 个虚拟字节),因此处理它很舒服。

要重用 bmp 对象中已处理的数据,您只需在处理后调用:

bmp.UnlockBits(bmpData);
于 2012-10-23T17:06:47.453 回答
1

如果您使用 C++,那么您也可以使用带有不安全代码的 C#。两者都是不安全的,在 C# 中你仍然不需要关心内存清理。您唯一需要关心的是访问无效指针,这将导致AccessViolationException.

public unsafe void SwapChannels(Byte[] imageSrc)
{
    fixed (Byte* pImageSrc = imageSrc)
    {
        // Swap channels here
    }
}

我也在我的图像库中使用了不安全的代码。如果你不打算跨平台,你也可以使用 C++/CLI。

于 2012-10-23T15:25:22.013 回答
1

有几种方法可以在 C++ 和 C# 之间进行互操作:C++/CLI、COM 和 P/Invoke。

C++/CLI 和 COM 都有可以更好的领域,但我认为不应该使用 P/Invoke,除了一些快速而肮脏的解决方案。

在您的情况下,特别是因为您提到 C++ DLL 是用另一个编译器构建的,我认为 COM 是您最好的选择。

但请注意,使用 C++ 非常类似于在 C# 中使用不安全代码。例如,到处都是指针。

于 2012-10-23T15:26:33.600 回答
0

SWIG允许您轻松包装 C++ 代码并在 c# 中公开类/函数。我用它在 c# 中公开了我的一些图像处理例程,这很容易。你最终得到的类表现为 c# classes,SWIG 生成的包装器处理类型转换(主要)和 P/Invoke 的东西。

swig.org 网站在我写这篇文章的那一刻已经关闭,如果有人知道原因,请发表评论

至于编译器混淆,我对 Mingw 编译的 DLL 有很好的经验。

编辑:您仍然可以访问项目 sourceforge 页面

于 2012-10-23T15:25:37.327 回答