2012-10-23 68 views
1

我在其中是基于C#我的主要程序编程的一些图形过滤器内。
但是对于getpixel/putpixel,C#并不快。
我已经看到了它的解决方法,在C#中使用不安全的代码
不安全的代码让我有点不安全的感觉也一样,我理解的安全码和内存清理的利益。使用C++ 11 C#程序

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

  • 一个人怎么会通过从C#中的位图在C++ 的功能,我可以设置参考DLL,但我不认为这将是足够的
  • 一个人怎么会通过一些返回值和位图返回到C#主程序

另外如果我用另一个编译器来编写C++ 11 .dll会是一个问题? 的主程序是用Visual Studio 2010中EXPRES

+0

使用C++/CLI:

重用从BMP对象,你处理它后只需要调用处理的数据。从C#直接调用,并且没有难看的不安全攻击 – Indy9000

回答

1

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

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

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

+1

而C#不安全的代码仍然可能比C++代码慢得多,比“安全”的C#代码更快。请注意,可能 - 不测量它只是一个猜测。 :D – NoSenseEtAl

+0

@NoSenseEtAl当然:http://davidthomasbernal.com/blog/2008/03/14/c-image-processing-performance-unsafe-vs-safe-code-part-ii/ –

+1

嗯这看起来很接近我想我会喜欢它的行为。 – user613326

0

SWIG允许您轻松地包裹C++代码,并在c#暴露类/功能。我用它在c#中公开了一些我的图像处理例程,这很容易。你最终得到的类作为c#类,SWIG生成的包装器处理类型转换(大部分)和P/Invoke的东西。

该网站swig.org是向下的那一刻我正在写,如果有人知道这是为什么,请评论

至于编译器的mixup我有MinGW的编译DLL很好的经验。

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

1

有几种方法来C++和C#之间的互操作做:C++/CLI,COM​​和P/Invoke的。

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

就你而言,特别是因为你提到C++ DLL是用另一个编译器构建的,所以我认为COM是你最好的选择。

但是请注意,使用C++是很像在C#中使用不安全的代码。例如,指点四周。

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

为了能够使用InteropServices使用它从C#项目,我导入该功能作为一个静态方法:

[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为指针位图数据和其他一些参数,如宽度,高度,步幅或任何你想要弄清楚C函数中的数据格式。在上面的例子中,每个像素将有4个字节(3个字节+ 1个空字节),因此处理它很舒服。

bmp.UnlockBits(bmpData);