.Heindl Solutions - C++ or C# for Machine Vision with HALCON

C++ or C# for Machine Vision with HALCON

2018-05-28 by Andreas Heindl



Most HALCON solutions have to be embedded in a host application (e.g. to provide graphical user interfaces) and then again most machine vision applications are implemented in C++ or C#. Here's our (somewhat opinionated) view on which host language should be used for your next HALCON project.

Complex decisions

The choice for a programming language is a strategic and longterm decision for a company to be made. It can hardly be explained in detail in a single blog post. We'll try our best to highlight some differences between C++ and C# ‐ the valuation and weighting must be carried out by a company or its HALCON developers.

Previous knowledge

If you or your HALCON vision application developers are only fluent in one of the languages it is a very substantial argument for this language. You need good reasons (maybe one of the following) to change to another language.

Support for HALCON

HALCON supports integration into C++ and C# host applications with the HALCON/C++ and HALCON/.NET interfaces. The performance of HALCON scripts will be similar in most cases.

Garbage Collector / Deterministic Destruction (RAII)

C++ has the RAII pattern and deterministic behaviour with objects going out of scope. Therefore we have the guarantee from the C++ language that every allocated HImage, e.g. in a image acquisition loop, is automatically freed afterwards and there will be no memory leak. In C#, it is often difficult to achieve this reliability and often manual and error prone effort is needed, e.g. a manually called myImage.Destroy() or a GCHandle.Free(). But these cleanup calls in C# can be missed easily if exceptions or early loop or function exits (continue, return) come into play. Furthermore, it is often impossible to make sure that the Garbage Collector does not run in an especially performance critical part of your application.

Managed vs. native

Native code is machine code for the target CPU as generated by a C++ compiler. It will be highly optimized but this optimization needs some time during the compilation. Therefore, C++ programs tend to have increased build times but fast startup times of the final application and especially fast processing performance.

In contrast, C# programs are compiled into intermediate bytecode only. This can be done relatively fast during the build, but the code won't be optimized as much as can be achieved with a good C++ compiler. The machine code finally generated at runtime will depend on the target system and therefore cannot be be analysed on the developer's machine.

As an example of what modern C++ compilers can achieve, take the following simple C++ snippet to count the number of set bits in an integer:

int count_bits_1(int a) {
    int count = 0;
    while (a) {
        count++;
        a &= (a-1);
    }
    return count;
}

This code compiles to

count_bits_1(int): # @count_bits_1(int)
popcnt eax, edi
ret

with the clang 6.0.0 compiler and it's easy to see the generated machine code / assembly code e.g. with Compiler Explorer. The optimization step of the C++ compiler understands the underlying algorithm and converts it into a single optimized popcnt instruction for Intel x86/x64 CPUs.

Windows

When developing C# code, one ofter targets Windows as the only operating system, although other target systems are possible in limited form (e.g. no WPF) by using the Mono project. C++ code can be written very portable and then runs on many different systems, for example using the Qt cross-platform application framework and widget toolkit.

HALCON Extension Packages, Image Acquisition Interfaces, Digital I/O Interfaces

If some functionality is missing in HALCON/HDevelop (certain hardware interfaces, customer specific image acquisition, …) it can be provided by custom Extension Packages, Image Acquistion Interfaces or Digital I/O Interfaces. These can be written in C or C++ language only.

External libraries / Open-source libraries

Many external libraries use the lowest common denominator as programming language, namely C or C++: It is possible to write a C# wrapper for C / C++ libraries, but it's not common to write a C++ wrapper for C# libraries. These C# wrappers for C++ libraries are sometimes outdated: For example, OpenCV 3.4 was released in December 2017 but until February 2018 the corresponding .NET-Wrapper Emgu.CV was only available for OpenCV 3.3.

Wrappers are often complicated to use, because they have to map C++ structures onto C#, which is not always a 100% fit: For example, the HALCON library is developed in C and has a C# wrapper (HALCON/.NET). Access to image matrices is complicated in C#:

GCHandle gch = GCHandle.Alloc(color_image);
image.GetImagePointer3(out pr, out pg, out pb, out type, out width, out height);
byte[] red_managed= new byte[width*height];
Marshal.Copy(pr, red_managed, 0, width*height);
// ...
gch.Free();

Most Windows internal libraries themselves are developed in C / C++ and in a way the .NET framework is only a wrapper for these libraries.

Hardware drivers

Some developments are only possible in C or C++, e.g. hardware drivers. Should these kinds of work be needed later and there exists only C# knowledge in a company, the necessary C++-knowledge has to be developed anew from scratch.

Debugging

Debugging in Visual Studio is sometimes easier with C#.

Example: HALCON exceptions

The code

HImage color_image = color_image_small.ZoomImageSize(4000, 3000, "WRONG"); 

throws in C# a meaningful

HalconDotNet.HOperatorException: 'HALCON error #3147: Wrong interpolation mode in operator zoom_image_size' 

but the C++ exception is meaningless:

Unhandled exception at 0x00007FFB288F3FB8 in MyApp.exe: Microsoft C++ exception: HalconCpp::HOperatorException at memory location 0x0000007469EFF718. 
Example: Watch of HALCON Tuples

C#:

var t = new HTuple();
t[0] = 42;
t[1] = "string";
Watch window: Name: t, Value: {[42, "string"]}

In C++ this introspection is not possible out-of-the-box:

HTuple t = HTuple(42).Append("string");
Watch window: Name: t, Value: <Information not available... 

On the other hand, the HALCON Variable Inspect extension is available for both programming languages.

Low level code

Low level code often runs much faster when developed in C++ :

Example: Color conversion

Sometimes, its necessary to use HALCON color images in a GUI framework. The GUI frameworks often use interleaved color formats (RGB RGB RGB …), while HALCON uses blocks of gray values per channel (RRR… GGG… BBB…). The conversion to the interleaved format for a certain color images takes 25 milliseconds in C++ but 60 milliseconds in C#. On the other hand, the performance differences between HALCON code called from C++ or HALCON code called from C# can often be neglected.

IDEs

There are many Integrated Development Environment (IDE) for C++, but less choices for a C# IDE.

Questions?

If you have any questions regarding this topic or and other HALCON related questions please do not hesitate to.