Cross-platform C SDK logo

Cross-platform C SDK

Welcome to NAppGUI

❮ Back
Next ❯
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.

While others were content to write programs that just solved problems, early hackers were obsessed with writing programs that solved problems well. A new program that achieved the same result as an existing one but used fewer punch cards was considered better, even if it did the same thing. The fundamental difference was how the program achieved its result. - elegance. Jon Erickson - Hacking: The Art of Exploitation


NAppGUI is an SDK for creating cross-platform native applications in C. By native software we understand that which is compiled/assembled using the specific instructions of the CPU (it is not interpreted or used bytecode) and by cross-platform the ability to build versions for Windows, macOS, and Linux using the same source code base (Figure 1). Since its first functions written in August 2010, the main objective of NAppGUI has been to simplify as much as possible the arduous task of creating applications with a graphical interface in C. Although different solutions already exist, we have opted for simplicity by creating a light abstraction layer that encapsulates native technologies, unifies them under the same API and adds some logic for task management and automation. Being somewhat more specific, the philosophy on which the project is based and some of its characteristics are:

Scheme that shows how the same source code can work on all versions of Windows, macOS and Linux.
Figure 1: Native cross-platform development with NAppGUI.
  • Rapid prototyping, evolution and maintenance in real applications, apart from the simple examples we find in the literature and the Internet.
  • The user interface is described using ANSI-C functions, completely eliminating visual design. This fact facilitates the creation of dynamic interfaces, guarantees portability and enables access to the API from any programming language.
  • Windows are composed and sized automatically, without the programmer having to explicitly indicate the coordinates and size of the controls.
  • It is possible to have a complete application in a single .c file, by removing the usual resource files (*.rc, *.xvid , etc) and their associated controllers. The programmer has complete freedom when defining his own file structure.
  • Automatic synchronization of internal data structures with the interface or with I/O channels. Data binding.
  • Unified management of resources which facilitates internationalization. Resources.
  • Translations between languages ​​at runtime without the need to restart the application. Runtime translation.
  • The compiled version of NAppGUI occupies less than 1Mb, and is distributed in several static libraries that generate very small executables. This is a great advantage over other solutions that require the distribution of heavy .DLLs, sometimes larger than the application itself.
  • Native Appearance: The applications will be integrated into each system respecting their original aesthetic (Figure 2).
  • Backends. The NAppGUI core provides structures and objects for creating highly efficient command-line applications on Windows or Linux servers.
  • Multiple screenshots showing the appearance of the same app on different operating systems.
    Figure 2: Native appearance of the Hello, World! demo.

1. Original APIs

Microsoft, Apple and GNU/Linux propose different APIs to interact with their systems. This means that the same application must be rewritten to work correctly on each platform. NAppGUI provides a unified set of functions for creating graphical user interfaces and allowing direct access to machine resources (memory, disk, network, etc.) (Figure 3). Each implementation takes into account the particular conditions of the target platform and uses the appropriate native commands to perform the task in the most optimal way possible.

Schema that shows the calls to the native APIs to create a button.
Figure 3: Calls to the native APIs, from the source code itself.

2. C-based

Despite the fact that today we have a large number of programming languages, the C language is still the most powerful and portable in the world. The core of Windows, macOS, Linux, Android, iOS, and other major programs are largely written in C. In the world of apps, its use has waned a bit in favor of more glamour. Perhaps this is one of the reasons why Wirth's law is more and more true every day.

"Software slows down faster than hardware speeds up."

NAppGUI is written, almost entirely, in C language with small parts in C++ and Objective-C. This language is widely supported and cross-platform compatible. In its development we have dispensed with minority, proprietary or brand-linked languages such as: C#, Swift, Java or Objective-C. Also interpreted (such as Python or JavaScript) and those based on virtual machines (Java and C#) due to the performance penalty (Figure 4). Finally, we have not used C++, since we do not present NAppGUI as a hierarchy of classes but as a library of functions. Our goals have been to minimize the impact of the SDK, simplify programming, increase readability, and produce high-performance binaries.

Different programming languages. From the slowest (interpreted) to the fastest (compiled).
Figure 4: Interpreter, virtual machine, and binary code. The closer we get to machine language, the more performance we will get from the software.

3. No visual editors

The creation of graphical interfaces can become a tedious process, since it is difficult to know in advance the final size of elements that contain text or images, such as buttons. On the other hand, windows are dynamic entities subject to changes at runtime (size, translation, changing subpanels, hidden areas, etc.). When using a visual editor, we have to place elements at the exact position and size (Figure 5). This is a mouse-intensive task, which slows down the connection between GUI objects and event handlers. In the development cycle, if the texts or other elements change (and of course they will), we will have to relocate the components by hand again. This problem grows in multilingual solutions. Keeping developers moving pixels and filling property forms is expensive for companies and very boring for them. This is not to mention that all of these visual designs will not be cross-platform compatible (.rc Windows, .xib macOS, .glade GTK/Gnome, etc.).

Screenshot of the interface editor included in Xcode.
Figure 5: Resource editors are not good friends for creating complex dynamic interfaces.
Many programmers prefer not to move their hands from the keyboard, since they consider it much more productive.

NAppGUI uses a declarative strategy, where it is only necessary to indicate the cell where the element will be located within a rectangular grid (Layout). The final size and position will be calculated at runtime, performing a recursive composition of the layouts and sublayouts based on their content (Listing 1) (Figure 6).

Listing 1: Creating a window.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Panel *panel = panel_create();
Layout *layout = layout_create(1, 3);
Label *label = label_create();
Button *button = button_push();
TextView *view = textview_create();
Window *window = window_create(ekWINDOW_STD);
label_text(label, "Hello!, I'm a label");
button_text(button, "Click Me!");
layout_label(layout, label, 0, 0);
layout_button(layout, button, 0, 1);
layout_textview(layout, view, 0, 2);
layout_hsize(layout, 0, 250);
layout_vsize(layout, 2, 100);
layout_margin(layout, 5);
layout_vmargin(layout, 0, 5);
layout_vmargin(layout, 1, 5);
panel_layout(panel, layout);
window_panel(window, panel);
window_title(window, "Hello, World!");
Simple user interface on Windows. Simple user interface on macOS from the same source code as Windows.
Figure 6: Declarative composition is fast, adaptable, and portable.

4. Dependencies

NAppGUI does not use third-party libraries, it only connects with the native APIs of each operating system. This fact, together with the use of C and static linking, makes it possible to:

  • Applications don't need additional runtimes like Python, Java, or C# do. They go directly to the CPU via the system scheduler.
  • The entire application can be contained in a single .exe file. As little code as possible is linked and no additional .dll need to be distributed. Starting with version 1.3, NAppGUI can be compiled as dynamic libraries.
  • Applications take up very little disk space, since all their dependencies are naturally present on the systems where they run.
  • The performance is maximum, since they are compiled in native machine code, using the highest level of optimization that each CPU supports.
  • They can be edited, compiled and run on obsolete platforms today like a Pentium III with Visual Studio 2005 and WindowsXP.
  • With NAppGUI we can move them from Windows to macOS or Linux, without touching a single line of source code. See Generators, compilers and IDEs.
  • C language is the fucking master.

Three packages within the SDK will act as technology wrappers (Figure 8), hiding platform-specific details under a common interface, without causing overhead to the program.

Baseline technologies that the SDK links to on each operating system.
Figure 8: Different technologies at the base of NAppGUI. In NAppGUI API you have the complete schematic.
  • Osbs: Operating System Basic Services. API about files and directories, processes, threads, memory, etc.
  • Draw2D: API for 2d vector drawing, images and fonts.
  • Gui: API about graphical interfaces: Windows, controls and menus.
  • Unix system calls: In Unix-like systems (Linux, macOS) it is the way in which a program communicates with the kernel to perform some task related to files, processes, memory, network or hardware usually.
  • Windows API: It is the lowest level API provided by Microsoft for programming under Windows. It is very broad and integrates different aspects of development:
    • kernel32.dll: The equivalent of Unix calls (files, processes, memory, etc).
    • ws2_32.dll: Provides TCP/IP network functions (Unix calls include TCP/IP support).
    • user32.dll, comctl32.dll, comdlg32.dll, uxtheme.dll: Implements standard controls for graphical user interfaces (labels, edit boxes, combos, progress bars, common dialogs, etc.).
  • Cocoa: Object-oriented programming API for Mac OSX (now macOS) systems. It is written in Objective-C, therefore it is not directly accessible from "pure" C. Cocoa is based on OpenStep, the API of NeXTSTEP, the operating system created by Steve Jobs when he was fired from Apple. In 1996, Apple buys NeXT and gets Jobs back, using Jobs' technology as the basis for the new Macintosh. Many classes in Cocoa still retain the NS prefix as NeXTSTEP inheritance. Although there is a lower level C-based API called Carbon, it has been discontinued since Mac OSX 10.4 Tiger. It does not have access to all system functionality nor is it compatible with 64-bit applications. Thus, Cocoa is the current lowest level API for Apple systems.
  • Gtk+: Acronym for GIMP ToolKit. It is a high-level library for creating graphical interfaces with a multitude of predefined objects (called widgets). It is one of the most widespread in GNU/Linux systems, but it is actually multiplatform with versions for Windows and macOS. Desktop environments like Gnome, Xfce or applications like GIMP are based on GTK.
  • GDI+: It is the evolution of GDI (Graphics Device Interface), a 2d vector drawing API developed by Microsoft for the first 16-bit version of Windows. GDI+ was introduced with Windows XP as a set of C++ classes and is encapsulated in the .NET platform via the System.Drawing namespace. It is also accessible directly from C via the GDI+ Flat API, but Microsoft recommends using it via C++ classes. It incorporates substantial improvements over GDI, such as floating point coordinates, affine transformations, anti-aliasing, gradient shading, and support for image formats such as JPG, PNG, or GIF. Drawing with masks and incompatibility with PDF are the two most notable drawbacks compared to Quartz 2D and Cairo, its direct "competitors" on other platforms.
  • Quartz 2D: It is the trade name of Core Graphics, the powerful drawing API of macOS. Like Cocoa, Core Graphics is an evolution of the NeXTSTEP graphics libraries and came to Apple after the NeXT acquisition. Quartz 2D is based on Adobe PostScript and PDF formats, incorporating alpha channel and anti-aliasing. Classic Macs (pre-NeXT) used the QuickDraw library, originally developed by Bill Atkinson for the Apple Lisa. Modern macs still have QuickDraw built in, but Xcode no longer provides headers, so it can't be used in new projects. Core Graphics is a C-based API and all of its functions begin with the CG prefix.
  • Cairo: Cairo is a C-based 2d vector drawing library. Unlike GDI+ or Quartz 2D, it is cross-platform, can be downloaded independently and incorporated into any project (under LGPL license). Since version 3, GTK+ uses Cairo for all widget drawing tasks. GTK+2 also used Cairo to generate PDF documents for printing. NAppGUI uses Cairo to implement the draw2d API on the GNU/Linux platform, as this library is found naturally in all GTK+ based desktop environments: Gnome, Cinnamon, LXDE, Mate, Pantheon, Sugar or Xfce. Technically, Cairo is quite advanced, matching Quartz 2D in terms of functionality. It supports affine transformations, image masks, bezier curves, text processing, and drawing on PDF and PostScript surfaces.
  • C stdlib: C is a beautiful little language, but it doesn't provide any additional support functions. During the 1970s, the C language became very popular and users began to share ideas on how to solve common and repetitive tasks. With its standardization in the 1980s, some of these ideas became the C standard library, which provides a basic set of mathematical functions, string manipulation, type conversions, and input/output. NAppGUI integrates in one way or another the functionality of the standard library, so we do not recommend its use in final applications (see Sewer).

5. Low and high level

During its design and implementation, NAppGUI has tried to maintain a balanced balance between low-level and high-level programming. Low-level lovers will find a kind of extended and cross-platform C library to access the system, interface elements and drawing commands. However, they will still retain the power to create optimized code and direct memory access. Remember, we are in C!

On the other hand, NAppGUI integrates some high-level solutions such as resource management, interface composition, automatic translations or data binding, among others. NAppGUI also incorporates CMake scripts for automated project creation in Visual Studio, Xcode, or Eclipse/Make.

Finally, it is the developers who decide which libraries to link with according to the needs of the project and the degree of automation they wish to adopt. Each application based on NAppGUI performs a static link of all its dependencies, so neither the executable nor its final distribution will have traces of unnecessary binary code. In this way, we will produce small self-contained executables that will not require an installer or include megabytes of dependencies in the form of .DLLs.

❮ Back
Next ❯