• Skip to main content
  • Skip to after header navigation
  • Skip to site footer

Free-Mail

  • Events
  • Images
    • Instagram Goodness
  • Music
  • News
  • Software

Boost the power of C with these open source libraries

Boost the power of C with these open source libraries: 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.

Why and how to handle exceptions in Python Flask
Image by:

Image from Unsplash.com, Creative Commons Zero 

Programming

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

: Opensource.com Joël Krähemann

Supporting Open Source.

Have you tried: Diving with Sharks?

Share this:

  • Share on Facebook (Opens in new window) Facebook
  • Share on X (Opens in new window) X
  • Share on Pinterest (Opens in new window) Pinterest
  • Email a link to a friend (Opens in new window) Email
  • More
  • Share on Tumblr (Opens in new window) Tumblr
  • Print (Opens in new window) Print
  • Share on LinkedIn (Opens in new window) LinkedIn
  • Share on Reddit (Opens in new window) Reddit
Published on 5 May 2022 by Alan Category: SoftwareTag: Boost, libraries, Open, Power, Source, These

A Thrilling Weekend of Gaming and Fun at Clearwater Mall Leg of the HYPROP MTN SHIFT Gaming Tournament

R200k in prize money, eight qualifiers nationwide, culminating in one epic gaming showdown… this is …

Read moreA Thrilling Weekend of Gaming and Fun at Clearwater Mall Leg of the HYPROP MTN SHIFT Gaming Tournament

Jerry Coovadia remembered – a champion of science, children and compassionate public health

Jerry Coovadia remembered – a champion of science, children and compassionate public health: …

Read moreJerry Coovadia remembered – a champion of science, children and compassionate public health

Zimbabwe seeks more power from Mozambique, Zambia

South Africa in the news: Zimbabwe seeks more power from Mozambique, Zambia: Zimbabwe is negotiating …

Read moreZimbabwe seeks more power from Mozambique, Zambia

About Alan

Previous Post:Cool Cape Town docks image
Next Post:Trending Now: Homer

Reach Trust

Reach Trust is a holding trust for a number of companies within the Stratlec Group.

Copyright © 2026 · Free-Mail · All Rights Reserved · Powered by Straton Electrical

Back to top