Open-source News

Fedora Linux 36 Being Released Next Week

Phoronix - Fri, 05/06/2022 - 02:00
After being delayed a few weeks from their original release target, Fedora 36 is now primed for release next week Tuesday...

Mesa's "Rusticl" Implementation Now Manages To Handle Darktable OpenCL

Phoronix - Fri, 05/06/2022 - 00:00
Rusticl as what started out as a Rust language experiment for Mesa and has now matured into a working OpenCL 3.0 implementation for Mesa drivers is still making progress and on a path towards eventually being mainlined...

AMD Begins Working On "GFX11" Support For Open-Source Mesa Linux Graphics (RDNA3)

Phoronix - Thu, 05/05/2022 - 20:33
Following AMD's recent AMDGPU Linux kernel patches for the "GFX11" graphics block to be found with next-gen RDNA3 GPUs, AMD has now submitted the initial Mesa-side patches for GFX11/RDNA3 with a focus on their RadeonSI Gallium3D driver...

Intel Has A Solution For Hot Linux Laptops Draining The Battery While Trying To Sleep

Phoronix - Thu, 05/05/2022 - 20:00
For those with Intel laptop models that are quick to run hot and happen to find your laptop battery quickly being drained even when it should be in a deep sleep state, a solution is in the works for the Linux kernel that ultimately stems from S0ix failing due to the PCH overheating...

VMware's SVGA Gallium3D Driver Getting NIR'ed

Phoronix - Thu, 05/05/2022 - 19:10
Following the open-source NVIDIA "Nouveau" driver switching to NIR by default, the VMware SVGA Gallium3D driver has also landed NIR-to-TGSI support in mainline...

Google Working On Linux Encrypted Hibernation Support

Phoronix - Thu, 05/05/2022 - 18:17
Google engineers are working on encrypted hibernation support for the Linux kernel as part of offering strong hibernation support for Google Chromebook usage...

Alchemist/DG2 Compute, Tigerlake+ Security Fix Head To Intel's Linux 5.19 Graphics Code

Phoronix - Thu, 05/05/2022 - 17:53
We are nearing the cut-off for new feature code to land in the DRM-Next display/graphics drivers for Linux 5.19 while this morning Intel engineers sent in a final drm-intel-gt-next feature update ahead of this next kernel...

MediaTek MT8186 Display Support, Other SoC Enablement Coming To Linux 5.19

Phoronix - Thu, 05/05/2022 - 17:26
MediaTek has not officially announced the MT8186 SoC yet but there has been references to it within Chrome OS sources for months and various speculations about this new Chromebook-focused SoC. With Linux 5.19 there is going to be a lot of MT8186 enablement code landing...

Boost the power of C with these open source libraries

opensource.com - Thu, 05/05/2022 - 15:00
Boost the power of C with these open source libraries Joël Krähemann Thu, 05/05/2022 - 03:00 Register or Login to like Register or Login to like

The GLib Object System (GObject) is a library providing a flexible and extensible object-oriented framework for C. In this article, I demonstrate using the 2.4 version of the library.

Programming and development Red Hat Developers Blog Programming cheat sheets Try for free: Red Hat Learning Subscription eBook: An introduction to programming with Bash Bash shell scripting cheat sheet eBook: Modernizing Enterprise Java

The GObject libraries extend the ANSI C standard, with typedefs for common types such as:

  • gchar: a character type
  • guchar: an unsigned character type
  • gunichar: a fixed 32 bit width unichar type
  • gboolean: a boolean type
  • gint8, gint16, gint32, gint64: 8, 16, 32, and 64 bit integers
  • guint8, guint16, guint32, guint64: unsigned 8, 16, 32, and 64 bit integers
  • gfloat: an IEEE Standard 754 single precision floating point number
  • gdouble: an IEEE Standard 754 double precision floating point number
  • gpointer: a generic pointer type
Function pointers

GObject also introduces a type and object system with classes and interfaces. This is possible because the ANSI C language understands function pointers.

To declare a function pointer, you can do this:

void (*my_callback)(gpointer data);

But first, you need to assign the my_callback variable:

void my_callback_func(gpointer data)
{
  //do something
}

my_callback = my_callback_func;

The function pointer my_callback can be invoked like this:

gpointer data;
data = g_malloc(512 * sizeof(gint16));
my_callback(data);Object classes

The GObject base class consists of 2 structs (GObject and GObjectClass) which you inherit to implement your very own objects.

You embed GObject and GObjectClass as the first struct field:

struct _MyObject
{
  GObject gobject;
  //your fields
};

struct _MyObjectClass
{
  GObjectClass gobject;
  //your class methods
};

GType my_object_get_type(void);

The object’s implementation contains fields, which might be exposed as properties. GObject provides a solution to private fields, too. This is actually a struct in the C source file, instead of the header file. The class usually contains function pointers only.

An interface can’t be derived from another interface and is implemented as following:

struct _MyInterface
{
  GInterface ginterface;
  //your interface methods
};

Properties are accessed by g_object_get() and g_object_set() function calls. To get a property, you must provide the return location of the specific type. It’s recommended that you initialize the return location first:

gchar *str

str = NULL;

g_object_get(gobject,
  "my-name", &str,
  NULL);

Or you might want to set the property:

g_object_set(gobject,
  "my-name", "Anderson",
  NULL);The libsoup HTTP library

The libsoup project provides an HTTP client and server library for GNOME. It uses GObjects and the glib main loop to integrate with GNOME applications, and also has a synchronous API for use in command-line tools. First, create a libsoup session with an authentication callback specified. You can also make use of cookies.

SoupSession *soup_session;
SoupCookieJar *jar;

soup_session = soup_session_new_with_options(SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_BASIC,
  SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_DIGEST,
  NULL);

jar = soup_cookie_jar_text_new("cookies.txt",
  FALSE);    

soup_session_add_feature(soup_session, jar);
g_signal_connect(soup_session, "authenticate",
  G_CALLBACK(my_authenticate_callback), NULL);

Then you can create a HTTP GET request like the following:

SoupMessage *msg;
SoupMessageHeaders *response_headers;
SoupMessageBody *response_body;
guint status;
GError *error;

msg = soup_form_request_new("GET",
  "http://127.0.0.1:8080/my-xmlrpc",
  NULL);

status = soup_session_send_message(soup_session,
  msg);

response_headers = NULL;
response_body = NULL;

g_object_get(msg,
  "response-headers", &response_headers,
  "response-body", &response_body,
  NULL);

g_message("status %d", status);
cookie = NULL;
soup_message_headers_iter_init(&iter,
response_headers);

while(soup_message_headers_iter_next(&iter, &name, &value)){    
  g_message("%s: %s", name, value);
}

g_message("%s", response_body->data);
if(status == 200){
  cookie = soup_cookies_from_response(msg);
  while(cookie != NULL){
    char *cookie_name;
    cookie_name = soup_cookie_get_name(cookie->data);
    //parse cookies
    cookie = cookie->next;
  }
}

The authentication callback is called as the web server asks for authentication.

Here’s a function signature:

#define MY_AUTHENTICATE_LOGIN "my-username"
#define MY_AUTHENTICATE_PASSWORD "my-password"

void my_authenticate_callback(SoupSession *session,
  SoupMessage *msg,
  SoupAuth *auth,
  gboolean retrying,
  gpointer user_data)
{
  g_message("authenticate: ****");
  soup_auth_authenticate(auth,
                         MY_AUTHENTICATE_LOGIN,
                         MY_AUTHENTICATE_PASSWORD);
}A libsoup server

For basic HTTP authentication to work, you must specify a callback and server context path. Then you add a handler with another callback.

This example listens to any IPv4 address on localhost port 8080:

SoupServer *soup_server;
SoupAuthDomain *auth_domain;
GSocket *ip4_socket;
GSocketAddress *ip4_address;
MyObject *my_object;
GError *error;

soup_server = soup_server_new(NULL);
auth_domain = soup_auth_domain_basic_new(SOUP_AUTH_DOMAIN_REALM, "my-realm",
  SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, my_xmlrpc_server_auth_callback,
  SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, my_object,
  SOUP_AUTH_DOMAIN_ADD_PATH, "my-xmlrpc",
  NULL);

soup_server_add_auth_domain(soup_server, auth_domain);
soup_server_add_handler(soup_server,
  "my-xmlrpc",
  my_xmlrpc_server_callback,
  my_object,
  NULL);

ip4_socket = g_socket_new(G_SOCKET_FAMILY_IPV4,
  G_SOCKET_TYPE_STREAM,
  G_SOCKET_PROTOCOL_TCP,
  &error);

ip4_address = g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4),
  8080);
error = NULL;
g_socket_bind(ip4_socket,
  ip4_address,
  TRUE,
  &error);
error = NULL;
g_socket_listen(ip4_socket, &error);

error = NULL;
soup_server_listen_socket(soup_server,
  ip4_socket, 0, &error);

In this example code, there are two callbacks. One handles authentication, and the other handles the request itself.

Suppose you want a web server to allow a login with the credentials username my-username and the password my-password, and to set a session cookie with a random unique user ID (UUID) string.

gboolean my_xmlrpc_server_auth_callback(SoupAuthDomain *domain,
  SoupMessage *msg,
  const char *username,
  const char *password,
  MyObject *my_object)
{
  if(username == NULL || password == NULL){
    return(FALSE);
  }

  if(!strcmp(username, "my-username") &&
     !strcmp(password, "my-password")){
    SoupCookie *session_cookie;
    GSList *cookie;
    gchar *security_token;
    cookie = NULL;

    security_token = g_uuid_string_random();
    session_cookie = soup_cookie_new("my-srv-security-token",
      security_token,
      "localhost",
      "my-xmlrpc",
      -1);

     cookie = g_slist_prepend(cookie,
       session_cookie);  
     soup_cookies_to_request(cookie,
       msg);
    return(TRUE);
  }
  return(FALSE);
}

A handler for the context path my-xmlrpc:

void my_xmlrpc_server_callback(SoupServer *soup_server,
  SoupMessage *msg,
  const char *path,
  GHashTable *query,
  SoupClientContext *client,
  MyObject *my_object)
{
  GSList *cookie;
  cookie = soup_cookies_from_request(msg);
  //check cookies
}A more powerful C

I hope my examples show how the GObject and libsoup projects give C a very real boost. Libraries like these extend C in a literal sense, and by doing so they make C more approachable. They do a lot of work for you, so you can turn your attention to inventing amazing applications in the simple, direct, and timeless C language.

GObject and libsoup do a lot of work for you, so you can turn your attention to inventing amazing applications in C.

Image by:

Image from Unsplash.com, Creative Commons Zero 

Programming What to read next This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License. Register or Login to post a comment.

Pages