Search code examples
c#exceptionuwpraspberry-pi3windows-10-iot-core

UWP debug/release error with ntdll.dll for LED detection


I'm writing a UWP program to detect colors from LEDs, this program runs on a Raspberry Pi 3 with Windows 10 IoT with attached display.

What the program does is take a reference image with the LED turned off, then take a image from the LED turned on.

Both images are converted to the same pixelformat and then are cropped to a smaller size, in which only the LED is shown (both the reference and the lighted LED).

Then those picture parts are converted to grayscale which is followed by creating a difference picture of the two, so that only pixels that changed from the reference to the lighted LED are shown.

To do so I use the NuGet-Package portable.AForge.imaging. The code is shown below.

            LEDBildNeu = LEDBild.Clone(PixelFormat.Format24bppRgb);
            ReferenzbildNeu = Referenzbild.Clone(PixelFormat.Format24bppRgb);

            Crop cropping = new Crop(new System.Drawing.Rectangle(Convert.ToInt32(x), Convert.ToInt32(y), 100, 100));

            CroppedLED = cropping.Apply(LEDBildNeu);
            CroppedReferenz = cropping.Apply(ReferenzbildNeu);

            Grayscale grayscale = new Grayscale(0.2125, 0.7154, 0.0721);
            GrayscaleReferenz = grayscale.Apply(CroppedReferenz);
            GrayscaleLED = grayscale.Apply(CroppedLED);
            
            Difference difference = new Difference(GrayscaleReferenz);
            Differenzbild = difference.Apply(GrayscaleLED);

This code works fine as long as I'm in debug mode, all of the functions are working. However when I change to release mode, I get this error while building:

1>C:\Users\morsch.nuget\packages\microsoft.net.native.compiler\1.7.2\tools\Microsoft.NetNative.targets(697,5): warning : MCG : warning MCG0007: Unresolved P/Invoke method 'ntdll.dll!memcpy' for method 'System.Byte* AForge.SystemTools.memcpy(System.Byte*, System.Byte*, System.Int32)'. Calling this method would throw exception at runtime. Please make sure the P/Invoke either points to a Windows API allowed in UWP applications, or a native DLL that is part of the package. If for some reason your P/Invoke does not satisify those requirements, please use [DllImport(ExactSpelling=true) to indicate that you understand the implications of using non-UWP APIs.

1>C:\Users\morsch.nuget\packages\microsoft.net.native.compiler\1.7.2\tools\Microsoft.NetNative.targets(697,5): warning : MCG : warning MCG0007: Unresolved P/Invoke method 'ntdll.dll!memset' for method 'System.Byte* AForge.SystemTools.memset(System.Byte*, System.Int32, System.Int32)'. Calling this method would throw exception at runtime. Please make sure the P/Invoke either points to a Windows API allowed in UWP applications, or a native DLL that is part of the package. If for some reason your P/Invoke does not satisify those requirements, please use [DllImport(ExactSpelling=true) to indicate that you understand the implications of using non-UWP APIs.

When I run the code in release mode and get to the part where the difference picture is created, I get the exception

System.TypeLoadException: 'Unresolved P/Invoke method 'memcpy!ntdll.dll' from this method. Please look for this method in build warnings for more details.'

According to this 'memset' and 'memcpy' are not supported by UWP. My questions now are:

Why does the program run in debug mode without any problems even when those two entry points are not supported, but as soon as i turn to release mode I get the exceptions?

Is there a workaround for the problem?

I already tried to use

        [DllImport("ntdll.dll", EntryPoint = "memset")]

and

        [DllImport("ntdll.dll", EntryPoint = "memcpy")]

But either I did it wrong or it just don't work that way.

I know I could just program a workaround in which I check the pixels manually and create a new image, but I wanted to solve that problem if possible.


Solution

  • I found a solution which worked:

    Instead of downloading the portable.AForge package with NuGet i downloaded the portable.AForge from GitHub.

    Find the .cs-file called SystemTools.cs (located in AForge/Sources/Core/). Open it with any .cs editing porgram, now search for all code like

    #if !MONO
    ...
    #else
    

    and remove it.

    This clears the use of memcpu() or memset() from ntdll.dll. Save the SystemTools.cs, create the library and add the AForge-Package manually to the application.

    After the change it worked without any problems.