0

I'm working on an application in C# and have to use image manipulation in C++ with wrapper CLI. In this project, I have a C# byte[] which needs to be sent to the C++ application which needs it as an unsigned char*. I have found a very simple example project, but his project uses DllImport instead of CLI. GitHub

I did search on the internet and most of the time I find people using marschal.copy to achieve this, but when I do this I get the following error: Cannot convert from 'System.IntPtr' to 'byte*'.

This is the code that I use: C#

Image image = Image.FromFile("Image.bmp");
unsafe
{
    using (MemoryStream sourceImageStream = new MemoryStream())
    {
        image.Save(sourceImageStream, System.Drawing.Imaging.ImageFormat.Png);
        byte[] sourceImagePixels = sourceImageStream.ToArray();

        // Initialize unmanaged memory to hold the array.
        int size = Marshal.SizeOf(sourceImagePixels[0]) * sourceImagePixels.Length;

        IntPtr pnt = Marshal.AllocHGlobal(size);

        try
        {
            // Copy the array to unmanaged memory.
            Marshal.Copy(sourceImagePixels, 0, pnt, sourceImagePixels.Length);

        }
        finally
        {
            // Free the unmanaged memory.
            Marshal.FreeHGlobal(pnt);
        }

        ImageManipulationCppWrapperC wrapper = new ImageManipulationCppWrapperC();
        wrapper.ConvertToGray(pnt, sourceImagePixels.Length); // pnt gives the error "Cannot convert from 'System.IntPtr' to 'byte*'"
        // wrapper.ConvertToGray(sourceImagePixels, sourceImagePixels.Length); sourceImagePixels gives error: "Cannot convert from 'byte[]' to 'byte*'"
    }
}

CLI

void ImageManipulationCppWrapperC::ConvertToGray(unsigned char* data, int dataLen)
{
    imP->ConvertToGray(data, dataLen);
}

bool ImageManipulationCppWrapperC::ReleaseMemoryFromC(unsigned char* buf)
{
    return imP->ReleaseMemoryFromC(buf);
}

C++

void ImageManipulationCpp::ConvertToGray(unsigned char* data, int dataLen)
{
    ...
}

So my question is, is it possible to send the byte[] to C++ with the use of CLI? and if so how can I do this?

wes
  • 379
  • 3
  • 15
  • 1
    Does [this answer your question](https://stackoverflow.com/questions/7707985/how-to-convert-arraysystembyte-to-char-in-c-clr)? – ChrisMM Nov 28 '19 at 13:28
  • @ChrisMM, I'm just starting with CLI, so I might be wrong at this. But doesn't the ^ mean a ref in C#? – wes Nov 28 '19 at 13:34
  • It is a GC pointer. They're created with `gcnew` (c++-cli), or regular `new` in C# – ChrisMM Nov 28 '19 at 13:37
  • @ChrisMM No its a regular `new`. `gcnew` isn't used in the project. – wes Nov 28 '19 at 13:39
  • Sorry, I just meant that c++ cli uses `gcnew` for objects created dynamically which the garbage collector maintains. Instead of using the `*` it uses `^`. The example I linked to is C++ cli, so the `^` in that case just means a pointer that the garbage collector will handle. See [here](https://stackoverflow.com/questions/202463/what-does-the-caret-mean-in-c-cli) for more info on that. – ChrisMM Nov 28 '19 at 13:42
  • @ChrisMM okay thank you for that. Sadly std::array expects more then 1 argument. I currently have this: `std::array^ bytearray` on the `>` I get the following error: `Too few arguments for class template "std::array"` – wes Nov 28 '19 at 13:49
  • In the linked code, the `array` is not an `std::array`, but a `System::array`. One of the annoying things about working with C++/CLI, is that `std` and `System` have a fair amount of classes named the same thing... – ChrisMM Nov 28 '19 at 13:50
  • @ChrisMM whoops, atleast I do not get an error, but now the assembly will not load... I have traced it back to this code `ImageManipulationCppWrapperC wrapper = new ImageManipulationCppWrapperC();` if I comment it the program will run. Do you have a quick fix for this? seems a bit strange that the assembly will no longer load after just a few code changes and no configuration change – wes Nov 28 '19 at 13:58
  • anyway `void ImageManipulationCpp::ConvertToGray(unsigned char* data, int dataLen)` <= terrible api, **what it does?** does it change something inside `data`? does it leave the same array size? – Selvin Nov 28 '19 at 14:00
  • Not entirely sure from what is given. Make sure that the C# project properly references the C++/CLI. I don't do too much work with .net anymore, so can't help much more, sorry. – ChrisMM Nov 28 '19 at 14:01
  • It is referenced alright, if I comment just this one line the program will run, but no call to C++ is made, I will do some research. first linked said to create a new project... – wes Nov 28 '19 at 14:04
  • Just use IntPtr as the argument type in your C++/CLI code. Call the native function with (unsigned char*)data.ToPointer() cast. – Hans Passant Nov 28 '19 at 14:10

0 Answers0