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

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

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

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

GLib 对象系统 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 库还引入了类和接口的类型和对象体系。之所以可以,是因为 ANSI C 语言可以理解函数指针。

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

“`
void (*my_callback)(gpointer data);

“`

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

“`
void mycallbackfunc(gpointer data)
{
//do something
}

mycallback = mycallback_func;

“`

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

“`
gpointer data;
data = gmalloc(512 * sizeof(gint16));
my
callback(data);

“`

对象类

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

你需要在结构体中先嵌入 GObjectGObjectClass

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

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

GType myobjectget_type(void);

“`

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

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

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

“`

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

“`
gchar *str

str = NULL;

gobjectget(gobject,
“my-name”, &str,
NULL);

“`

或者你想要设置属性:

“`
gobjectset(gobject,
“my-name”, “Anderson”,
NULL);

“`

libsoup HTTP 库

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

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

“`
SoupSession *soup_session;
SoupCookieJar *jar;

soupsession = soupsessionnewwithoptions(SOUPSESSIONADDFEATUREBYTYPE, SOUPTYPEAUTHBASIC,
SOUP
SESSIONADDFEATUREBYTYPE, SOUPTYPEAUTH_DIGEST,
NULL);

jar = soupcookiejartextnew(“cookies.txt”,
FALSE);

soupsessionaddfeature(soupsession, jar);
gsignalconnect(soupsession, “authenticate”,
G
CALLBACK(myauthenticatecallback), NULL);

“`

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

“`
SoupMessage *msg;
SoupMessageHeaders *responseheaders;
SoupMessageBody *response
body;
guint status;
GError *error;

msg = soupformrequest_new(“GET”,
“http://127.0.0.1:8080/my-xmlrpc”,
NULL);

status = soupsessionsendmessage(soupsession,
msg);

responseheaders = NULL;
response
body = NULL;

gobjectget(msg,
“response-headers”, &responseheaders,
“response-body”, &response
body,
NULL);

gmessage(“status %d”, status);
cookie = NULL;
soup
messageheadersiterinit(&iter,
response
headers);

while(soupmessageheadersiternext(&iter, &name, &value)){
g_message(“%s: %s”, name, value);
}

gmessage(“%s”, responsebody->data);
if(status == 200){
cookie = soupcookiesfromresponse(msg);
while(cookie != NULL){
char *cookie
name;
cookiename = soupcookiegetname(cookie->data);
//parse cookies
cookie = cookie->next;
}
}

“`

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

这是一个函数签名:

“`

define MYAUTHENTICATELOGIN “my-username”

define MYAUTHENTICATEPASSWORD “my-password”

void myauthenticatecallback(SoupSession session,
SoupMessage *msg,
SoupAuth *auth,
gboolean retrying,
gpointer user_data)
{
g_message(“authenticate: *
**”);
soupauthauthenticate(auth,
MYAUTHENTICATELOGIN,
MYAUTHENTICATEPASSWORD);
}

“`

一个 libsoup 服务器

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

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

“`
SoupServer *soupserver;
SoupAuthDomain *auth
domain;
GSocket *ip4socket;
GSocketAddress *ip4
address;
MyObject *my_object;
GError *error;

soupserver = soupservernew(NULL);
auth
domain = soupauthdomainbasicnew(SOUPAUTHDOMAINREALM, “my-realm”,
SOUP
AUTHDOMAINBASICAUTHCALLBACK, myxmlrpcserverauthcallback,
SOUPAUTHDOMAINBASICAUTHDATA, myobject,
SOUPAUTHDOMAINADDPATH, “my-xmlrpc”,
NULL);

soupserveraddauthdomain(soupserver, authdomain);
soupserveraddhandler(soupserver,
“my-xmlrpc”,
myxmlrpcservercallback,
my
object,
NULL);

ip4socket = gsocketnew(GSOCKETFAMILYIPV4,
GSOCKETTYPESTREAM,
G
SOCKETPROTOCOLTCP,
&error);

ip4address = ginetsocketaddressnew(ginetaddressnewany(GSOCKETFAMILYIPV4),
8080);
error = NULL;
gsocketbind(ip4socket,
ip4
address,
TRUE,
&error);
error = NULL;
gsocketlisten(ip4_socket, &error);

error = NULL;
soupserverlistensocket(soupserver,
ip4_socket, 0, &error);

“`

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

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

“`
gboolean myxmlrpcserverauthcallback(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 *sessioncookie;
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);
}

“`

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

“`
void myxmlrpcservercallback(SoupServer *soupserver,
SoupMessage *msg,
const char *path,
GHashTable *query,
SoupClientContext *client,
MyObject *myobject)
{
GSList *cookie;
cookie = soup
cookiesfromrequest(msg);
//check cookies
}

“`

更加强大的 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中国 荣誉推出

主题测试文章,只做测试使用。发布者:eason,转转请注明出处:https://aicodev.cn/2022/09/24/%e4%bd%bf%e7%94%a8%e5%bc%80%e6%ba%90%e5%ba%93-gobject-%e5%92%8c-libsoup-%e6%8f%90%e5%8d%87-c-%e8%af%ad%e8%a8%80%e7%bc%96%e7%a8%8b%e8%83%bd%e5%8a%9b/

Like (0)
eason的头像eason
Previous 2022年9月24日
Next 2022年9月25日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信