在c#程序中使用c ++ 11

时间:2012-10-23 15:18:11

标签: c# c++ c++11 interop

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

所以现在我想知道.... 可能最好在基于C ++的分离dll中编写这个不安全的代码吗? 但是我从来没有制作混合语言课程,所以我很想知道。

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

如果我用另一个编译器来编写c ++ 11 .dll会是一个问题呢? 主程序是用visual studio 2010 expres编写的

4 个答案:

答案 0 :(得分: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);

答案 1 :(得分:1)

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

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

我也在我的图片库中使用不安全的代码。如果您不进行跨平台,也可以使用C ++ / CLI。

答案 2 :(得分:1)

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

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

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

但请注意,使用C ++非常类似于在C#中使用不安全的代码。例如,指针四周。

答案 3 :(得分:0)

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

网站swig.org在我写作的那一刻下来,如果有人知道为什么,请发表评论

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

编辑:您仍然可以访问project sourceforge page