1 Bibtex文献类的设计
1.1 Bibtex类头文件
/* file name: my-bibtex.h */
#ifndef KB_BIBTEX_H
#define KB_BIBTEX_H
#include<glib-object.h>
#define MY_TYPE_BIBTEX (my_bibtex_get_type())
#define MY_BIBTEX(object) \
G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_BIBTEX, MyBibtex)
typedef struct _MyBibtex MyBibtex;
struct _MyBibtex{
GObject parent;
};
typedef struct _MyBibtexClass MyBibtexClass;
struct _MyBibtexClass{
GObjectClass parent_class;
};
GType my_bibtex_get_type(void);
void
my_bibtex_printf(MyBibtex *self);
#endif
1.2 Bibtex类函数实现
#include"my-bibtex.h"
/* 类型注册 系统自动生成my_bibtex_get_type()函数 */
G_DEFINE_TYPE (MyBibtex, my_bibtex, G_TYPE_OBJECT);
#define MY_BIBTEX_GET_PRIVATE(object) (\
G_TYPE_INSTANCE_GET_PRIVATE ((object), MY_TYPE_BIBTEX, MyBibtexPrivate))
/* 对象私有属性 */
typedef struct _MyBibtexPrivate MyBibtexPrivate;
struct _MyBibtexPrivate{
GString *title;
GString *author;
GString *publisher;
guint year;
};
enum PROPERTY_BIBTEX {
PROPERTY_0,
PROPERTY_TITLE,
PROPERTY_AUTHOR,
PROPERTY_PUBLISHER,
PROPERTY_YEAR,
N_PROPERTIES
};
static void
my_bibtex_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
MyBibtex *self = MY_BIBTEX (object);
MyBibtexPrivate *priv = MY_BIBTEX_GET_PRIVATE (self);
switch (property_id) {
case PROPERTY_TITLE:
if (priv->title)
g_string_free (priv->title, TRUE);
priv->title = g_string_new (g_value_get_string (value));
break;
case PROPERTY_AUTHOR:
if (priv->author)
g_string_free (priv->author, TRUE);
priv->author = g_string_new (g_value_get_string (value));
break;
case PROPERTY_PUBLISHER:
if (priv->publisher)
g_string_free (priv->publisher, TRUE);
priv->publisher = g_string_new (g_value_get_string (value));
break;
case PROPERTY_YEAR:
priv->year = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
my_bibtex_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
MyBibtex *self = MY_BIBTEX (object);
MyBibtexPrivate *priv = MY_BIBTEX_GET_PRIVATE (self);
GString *similar = NULL;
switch (property_id) {
case PROPERTY_TITLE:
g_value_set_string (value, priv->title->str);
break;
case PROPERTY_AUTHOR:
g_value_set_string (value, priv->author->str);
break;
case PROPERTY_PUBLISHER:
g_value_set_string (value, priv->publisher->str);
break;
case PROPERTY_YEAR:
g_value_set_uint (value, priv->year);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/* 参数名之所以使用klass而不是class,为了C++编译的时候防止和关键字class冲突 */
static void
my_bibtex_class_init (MyBibtexClass *klass)
{
g_type_class_add_private (klass,
sizeof (MyBibtexPrivate));
GObjectClass *base_class = G_OBJECT_CLASS (klass);
base_class->set_property = my_bibtex_set_property;
base_class->get_property = my_bibtex_get_property;
GParamSpec *properties[N_PROPERTIES] = {NULL,};
properties[PROPERTY_TITLE] =
g_param_spec_string ("title",
"Title",
"Bibliography title",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_AUTHOR] =
g_param_spec_string ("author",
"Author",
"Bibliography author",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_PUBLISHER] =
g_param_spec_string ("publisher",
"Publisher",
"Bibliography Publisher",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_YEAR] =
g_param_spec_uint ("year",
"Year",
"Bibliography year",
0,
G_MAXUINT,
0,
G_PARAM_READWRITE);
g_object_class_install_properties (base_class, N_PROPERTIES, properties);
}
static void
my_bibtex_init (MyBibtex *self)
{
}
void
my_bibtex_printf(MyBibtex *self)
{
gchar *title, *author, *publisher;
gint year;
g_object_get(G_OBJECT(self),
"title", &title,
"author", &author,
"publisher", &publisher,
"year", &year,
NULL);
g_printf(" Title: %s\n"
" Author: %s\n"
"Publisher: %s\n"
" Year: %d\n", title, author, publisher, year);
/*g_free 是因为系统重新创建了字符串内存空间,没有指向私有属性的地址*/
g_free(title);
g_free(author);
g_free(publisher);
}
分析
除了构造类属性,与前面的有所区别,本文采用的是ParamSpec类型的指针数组,一遍在类属性构造完毕后,使用个g_object_class_install_properties函数一并安装到类结构体中。 而不是像上一篇文档那样g_object_class_install_property一个一个安装。
打印输出文献信息函数,为什么要释放内存。因为get_property属性的时候,新建的一个字符串变量。该变量不等于私有属性字符串变量地址。故必须释放,且不会引起私有属性错误。
2 Article文献类的设计
2.1 Article文献类头文件
#include"my-bibtex.h"
/* 类的数据类型获取函数宏 */
#define MY_TYPE_ARTICLE (my_article_get_type())
#define MY_ARTICLE(object) \
G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_ARTICLE, MyArticle)
typedef struct _MyArticle MyArticle;
struct _MyArticle{
MyBibtex parent;
};
typedef struct _MyArticleClass MyArticleClass;
struct _MyArticleClass{
MyBibtexClass parent_class;
};
GType
my_article_get_type();
void
my_article_printf(MyArticle *self);
分析
类实例结构体和类结构体都是继承与MyBibtex类。
2.2 Article类函数实现
#include"my-article.h"
#include"my-bibtex.h"
G_DEFINE_TYPE(MyArticle, my_article, MY_TYPE_BIBTEX);
#define MY_ARTICLE_GET_PRIVATE(object) (\
G_TYPE_INSTANCE_GET_PRIVATE ((object), MY_TYPE_ARTICLE, MyArticlePrivate))
/* 对象私有属性 */
typedef struct _MyArticlePrivate MyArticlePrivate;
struct _MyArticlePrivate{
GString *journal;
GString *volume;
GString *number;
GString *pages;
};
enum PROPERTY_ARTICLE {
PROPERTY_0,
PROPERTY_JOURNAL,
PROPERTY_VOLUME,
PROPERTY_NUMBER,
PROPERTY_PAGES,
N_PROPERTIES
};
static void
my_article_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
MyArticle *self = MY_ARTICLE (object);
MyArticlePrivate *priv = MY_ARTICLE_GET_PRIVATE (self);
switch (property_id) {
case PROPERTY_JOURNAL:
if (priv->journal)
g_string_free (priv->journal, TRUE);
priv->journal = g_string_new (g_value_get_string (value));
break;
case PROPERTY_VOLUME:
if (priv->volume)
g_string_free (priv->volume, TRUE);
priv->volume = g_string_new (g_value_get_string (value));
break;
case PROPERTY_NUMBER:
if (priv->number)
g_string_free (priv->number, TRUE);
priv->number = g_string_new (g_value_get_string (value));
break;
case PROPERTY_PAGES:
if (priv->pages)
g_string_free (priv->pages, TRUE);
priv->pages = g_string_new (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
my_article_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
MyArticle *self = MY_ARTICLE (object);
MyArticlePrivate *priv = MY_ARTICLE_GET_PRIVATE (self);
GString *similar = NULL;
switch (property_id) {
case PROPERTY_JOURNAL:
g_value_set_string (value, priv->journal->str);
break;
case PROPERTY_VOLUME:
g_value_set_string (value, priv->volume->str);
break;
case PROPERTY_NUMBER:
g_value_set_string (value, priv->number->str);
break;
case PROPERTY_PAGES:
g_value_set_string (value, priv->pages->str);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/* 参数名之所以使用klass而不是class,为了C++编译的时候防止和关键字class冲突 */
static void
my_article_class_init (MyArticleClass *klass)
{
g_type_class_add_private (klass,
sizeof (MyArticlePrivate));
GObjectClass *base_class = G_OBJECT_CLASS (klass);
g_printf("Article***: %p\n", base_class);
base_class->set_property = my_article_set_property;
base_class->get_property = my_article_get_property;
GParamSpec *properties[N_PROPERTIES] = {NULL,};
properties[PROPERTY_JOURNAL] =
g_param_spec_string ("journal",
"Journal",
"Bibliography journal",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_VOLUME] =
g_param_spec_string ("volume",
"Volume",
"Bibliography volume",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_NUMBER] =
g_param_spec_string ("number",
"Number",
"Bibliography number",
NULL,
G_PARAM_READWRITE);
properties[PROPERTY_PAGES] =
g_param_spec_string ("pages",
"Pages",
"Bibliography pages",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (base_class, N_PROPERTIES, properties);
}
static void
my_article_init (MyArticle *self)
{
}
void
my_article_printf(MyArticle *self)
{
my_bibtex_printf(&self->parent);
gchar *journal, *volume, *number, *pages;
g_object_get(G_OBJECT(self),
"journal", &journal,
"volume", &volume,
"number", &number,
"pages", &pages,
NULL);
g_printf(" Journal: %s\n"
" Volume: %s\n"
" Number: %s\n"
" Pages: %s\n", journal, volume, number, pages);
/*g_free 是因为系统重新创建了字符串内存空间,没有指向私有属性的地址*/
g_free(journal);
g_free(volume);
g_free(number);
g_free(pages);
}
分析
G_DEFINE_TYPE(MyArticle, my_article, MY_TYPE_BIBTEX);
第三个参数是父类结构体信息。
3 主函数的实现
#include"my-bibtex.h"
#include"my-article.h"
int
main (void)
{
g_type_init ();
MyArticle *entry = g_object_new (MY_TYPE_ARTICLE,
"title", "Breaking paragraphs into lines",
"author", "Knuth, D.E. and Plass, M.F.",
"publisher", "Wiley Online Library",
"journal", "Software: Practice and Experience",
"volume", "11",
"number", "11",
"year", 1981,
"pages", "1119-1184",
NULL);
my_article_printf (entry);
g_object_unref (entry);
return 0;
}