使用开源库 GObject 和 libsoup 提升 C 语言编程能力

admin 2022年9月25日20:55:43评论49 views字数 5505阅读18分21秒阅读模式
 
使用开源库 GObject 和 libsoup 提升 C 语言编程能力
导读:开源库 GObject 和 libsoup 做了很多工作,因此你可以专注于使用 C 语言开发神奇的应用。
使用开源库 GObject 和 libsoup 提升 C 语言编程能力本文字数:7023,阅读时长大约:7分钟

开源库 GObject 和 libsoup 做了很多工作,因此你可以专注于使用 C 语言开发神奇的应用。

GLib 对象系统🔗 docs.gtk.org(Object System)(GObject)是一个为 C 语言提供灵活且可扩展的面向对象框架的库。在这篇文章中,我将使用该库的 2.4 版本进行演示。

GObject 库继承了 ANSI C 标准,拥有一些常见的数据类型,例如:

◈ gchar:字符型
◈ guchar:无符号字符型
◈ gunichar:32 位定宽 Unicode 字符型
◈ gboolean:布尔型
◈ gint8gint16gint32gint64:有符号 8、16、32 和 64 位整数
◈ guint8guint16guint32guint64:无符号 8、16、32 和 64 位整数
◈ gfloat:IEEE 754 标准单精度浮点数
◈ gdouble:IEEE 754 标准双精度浮点数
◈ gpointer:泛指针

使用开源库 GObject 和 libsoup 提升 C 语言编程能力

函数指针

GObject 库还引入了类和接口的类型和对象体系。之所以可以,是因为 ANSI C 语言可以理解函数指针。

你可以这样做来声明函数指针:

  1. void (*my_callback)(gpointer data);

首先,你需要给变量 my_callback 赋值:

  1. void my_callback_func(gpointer data)
  2. {
  3.   //do something
  4. }
  5. my_callback = my_callback_func;

函数指针 my_callback 可以这样来调用:

  1. gpointer data;
  2. data = g_malloc(512 * sizeof(gint16));
  3. my_callback(data);

使用开源库 GObject 和 libsoup 提升 C 语言编程能力

对象类

GObject 基类由 2 个结构(GObject 和 GObjectClass)组成,你可以继承它们以实现你自己的对象。

你需要在结构体中先嵌入 GObject 和 GObjectClass

  1. struct _MyObject
  2. {
  3.   GObject gobject;
  4.   //your fields
  5. };
  6. struct _MyObjectClass
  7. {
  8.   GObjectClass gobject;
  9.   //your class methods
  10. };
  11. GType my_object_get_type(void);

对象的实现包含了公有成员。GObject 也提供了私有成员的方法。这实际上是 C 源文件中的一个结构,而不是在头文件。该类通常只包含函数指针。

一个接口不能派生自另一个接口,比如:

  1. struct _MyInterface
  2. {
  3.   GInterface ginterface;
  4.   //your interface methods
  5. };

通过调用 g_object_get() 和 g_object_set() 函数来访问属性。若要获取属性,你必须提供特定类型的返回位置。建议先初始化返回位置:

  1. gchar *str
  2. str = NULL;
  3. g_object_get(gobject,
  4.   "my-name", &str,
  5.   NULL);

或者你想要设置属性:

  1. g_object_set(gobject,
  2.   "my-name", "Anderson",
  3.   NULL);

使用开源库 GObject 和 libsoup 提升 C 语言编程能力

libsoup HTTP 库

libsoup 项目为 GNOME 提供了 HTTP 客服端和服务端使用的库。它使用 GObjects 和 glib 主循环与集成到 GNOME 应用,并且还具有用于命令行的同步 API。

首先,创建一个特定身份验证回调的 libsoup 会话。你也可以使用 cookie。

  1. SoupSession *soup_session;
  2. SoupCookieJar *jar;
  3. soup_session = soup_session_new_with_options(SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_BASIC,
  4.   SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_DIGEST,
  5.   NULL);
  6. jar = soup_cookie_jar_text_new("cookies.txt",
  7.   FALSE);    
  8. soup_session_add_feature(soup_session, jar);
  9. g_signal_connect(soup_session, "authenticate",
  10.   G_CALLBACK(my_authenticate_callback), NULL);

然后你可以像这样创建一个 HTTP GET 请求:

  1. SoupMessage *msg;
  2. SoupMessageHeaders *response_headers;
  3. SoupMessageBody *response_body;
  4. guint status;
  5. GError *error;
  6. msg = soup_form_request_new("GET",
  7.   "http://127.0.0.1:8080/my-xmlrpc",
  8.   NULL);
  9. status = soup_session_send_message(soup_session,
  10.   msg);
  11. response_headers = NULL;
  12. response_body = NULL;
  13. g_object_get(msg,
  14.   "response-headers", &response_headers,
  15.   "response-body", &response_body,
  16.   NULL);
  17. g_message("status %d", status);
  18. cookie = NULL;
  19. soup_message_headers_iter_init(&iter,
  20. response_headers);
  21. while(soup_message_headers_iter_next(&iter, &name, &value)){    
  22.   g_message("%s: %s", name, value);
  23. }
  24. g_message("%s", response_body->data);
  25. if(status == 200){
  26.   cookie = soup_cookies_from_response(msg);
  27.   while(cookie != NULL){
  28.     char *cookie_name;
  29.     cookie_name = soup_cookie_get_name(cookie->data);
  30.     //parse cookies
  31.     cookie = cookie->next;
  32.   }
  33. }

当网络服务器进行身份认证时,会调用身份认证回调函数。

这是一个函数签名:

  1. #define MY_AUTHENTICATE_LOGIN "my-username"
  2. #define MY_AUTHENTICATE_PASSWORD "my-password"
  3. void my_authenticate_callback(SoupSession *session,
  4.   SoupMessage *msg,
  5.   SoupAuth *auth,
  6.   gboolean retrying,
  7.   gpointer user_data)
  8. {
  9.   g_message("authenticate: ****");
  10.   soup_auth_authenticate(auth,
  11.                          MY_AUTHENTICATE_LOGIN,
  12.                          MY_AUTHENTICATE_PASSWORD);
  13. }

使用开源库 GObject 和 libsoup 提升 C 语言编程能力

一个 libsoup 服务器

想要基础的 HTTP 身份认证能够运行,你需要指定回调函数和服务器上下文路径。然后再添加一个带有另一个回调的处理程序。

下面这个例子展示了在 8080 端口监听任何 IPv4 地址的消息:

  1. SoupServer *soup_server;
  2. SoupAuthDomain *auth_domain;
  3. GSocket *ip4_socket;
  4. GSocketAddress *ip4_address;
  5. MyObject *my_object;
  6. GError *error;
  7. soup_server = soup_server_new(NULL);
  8. auth_domain = soup_auth_domain_basic_new(SOUP_AUTH_DOMAIN_REALM, "my-realm",
  9.   SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, my_xmlrpc_server_auth_callback,
  10.   SOUP_AUTH_DOMAIN_BASIC_AUTH_DATA, my_object,
  11.   SOUP_AUTH_DOMAIN_ADD_PATH, "my-xmlrpc",
  12.   NULL);
  13. soup_server_add_auth_domain(soup_server, auth_domain);
  14. soup_server_add_handler(soup_server,
  15.   "my-xmlrpc",
  16.   my_xmlrpc_server_callback,
  17.   my_object,
  18.   NULL);
  19. ip4_socket = g_socket_new(G_SOCKET_FAMILY_IPV4,
  20.   G_SOCKET_TYPE_STREAM,
  21.   G_SOCKET_PROTOCOL_TCP,
  22.   &error);
  23. ip4_address = g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4),
  24.   8080);
  25. error = NULL;
  26. g_socket_bind(ip4_socket,
  27.   ip4_address,
  28.   TRUE,
  29.   &error);
  30. error = NULL;
  31. g_socket_listen(ip4_socket, &error);
  32. error = NULL;
  33. soup_server_listen_socket(soup_server,
  34.   ip4_socket, 0, &error);

示例代码中,有两个回调函数。一个处理身份认证,另一个处理对它的请求。

假设你想要网页服务器允许用户名为 my-username 和口令为 my-password 的凭证登录,并且用一个随机且唯一的用户 ID 字符串设置会话 cookie。

  1. gboolean my_xmlrpc_server_auth_callback(SoupAuthDomain *domain,
  2.   SoupMessage *msg,
  3.   const char *username,
  4.   const char *password,
  5.   MyObject *my_object)
  6. {
  7.   if(username == NULL || password == NULL){
  8.     return(FALSE);
  9.   }
  10.   if(!strcmp(username, "my-username") &&
  11.      !strcmp(password, "my-password")){
  12.     SoupCookie *session_cookie;
  13.     GSList *cookie;
  14.     gchar *security_token;
  15.     cookie = NULL;
  16.     security_token = g_uuid_string_random();
  17.     session_cookie = soup_cookie_new("my-srv-security-token",
  18.       security_token,
  19.       "localhost",
  20.       "my-xmlrpc",
  21.       -1);
  22.      cookie = g_slist_prepend(cookie,
  23.        session_cookie);  
  24.      soup_cookies_to_request(cookie,
  25.        msg);
  26.     return(TRUE);
  27.   }
  28.   return(FALSE);
  29. }

对上下文路径 my-xmlrpc 进行处理的函数:

  1. void my_xmlrpc_server_callback(SoupServer *soup_server,
  2.   SoupMessage *msg,
  3.   const char *path,
  4.   GHashTable *query,
  5.   SoupClientContext *client,
  6.   MyObject *my_object)
  7. {
  8.   GSList *cookie;
  9.   cookie = soup_cookies_from_request(msg);
  10.   //check cookies
  11. }

使用开源库 GObject 和 libsoup 提升 C 语言编程能力

更加强大的 C 语言

希望我的示例展现了 GObject 和 libsoup 项目给 C 语言带来了真正的提升。像这样在字面意义上扩展 C 语言,可以使 C 语言更易于使用。它们已经为你做了许多工作,这样你可以专注于用 C 语言开发简单、直接的应用程序了。


via: https://opensource.com/article/22/5/libsoup-gobject-c

作者:Joël Krähemann 选题:lkxed 译者:Donkey-Hao 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用开源库 GObject 和 libsoup 提升 C 语言编程能力
LCTT 译者 :Donkey
🌟🌟🌟
使用开源库 GObject 和 libsoup 提升 C 语言编程能力
翻译: 21.0 篇

|

贡献: 104 天
2022-06-09
2022-09-21
https://linux.cn/lctt/Donkey-Hao
欢迎遵照 CC-BY-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。

原文始发于微信公众号(Linux中国):使用开源库 GObject 和 libsoup 提升 C 语言编程能力 | Linux 中国

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月25日20:55:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   使用开源库 GObject 和 libsoup 提升 C 语言编程能力https://cn-sec.com/archives/1314619.html

发表评论

匿名网友 填写信息