在上一篇文章中,我们讨论了如何创建一个基本的Ruby C扩展程序,以使我们能够从Ruby中调用C代码。在本文中,我们将继续这个话题,讨论如何利用此功能从Ruby中调用Clips规则引擎。

作为熟悉Clips的读者可能会知道,Clips是一个基于C编写的规则引擎。这意味着我们可以直接从Ruby中调用Clips的C函数,而不必通过Clips的命令行接口或socket连接来间接使用它。我们可以将这一切通过C扩展程序的API进行封装,然后从Ruby中进行调用。

为了演示此过程,我们将创建一个简单的Ruby类,该类将允许我们在Ruby中创建一个Clips环境,并加载此环境中的规则文件,并运行该环境中的规则引擎。让我们从编写C扩展程序开始。

“`c

#include

#include “CLIPS/clips.h”

VALUE ClipsEnvironment = Qnil;

void Init_clips() {

ClipsEnvironment = rb_define_module(“ClipsEnvironment”);

}

“`

这是我们的C扩展程序的起点。 此代码的作用是在Ruby中创建一个名为“ClipsEnvironment”的模块。 此模块将用于我们将要创建的此程序API的所有功能。

现在让我们编写一个函数,该函数可以使用Clips创建一个环境。

“`c

static VALUE create_clips_environment(VALUE self) {

void* clipsEnv = CreateEnvironment();

return (VALUE)clipsEnv;

}

void Init_clips() {

ClipsEnvironment = rb_define_module(“ClipsEnvironment”);

rb_define_module_function(ClipsEnvironment, “create_environment”, create_clips_environment, 0);

}

“`

上述函数使用Clips中的CreateEnvironment函数在内存中创建一个新的Clips环境。 然后我们将环境作为指向Ruby对象的指针返回。我们还定义了一个名为“create_environment”的函数,该函数可以从Ruby中访问我们刚刚编写的C函数。

接下来,我们将在Clips环境中加载一个规则文件。 下面是加载规则文件的函数:

“`c

static VALUE load_rules_file(VALUE self, VALUE clipsEnvironment, VALUE fileName) {

Environment* env = (Environment*)clipsEnvironment;

int clipsStatus = Load(env, StringValueCStr(fileName));

if (!clipsStatus) {

VALUE errorMessage = rb_str_new2(“Failed to load rules file”);

rb_exc_raise(errorMessage);

}

return Qnil;

}

void Init_clips() {

ClipsEnvironment = rb_define_module(“ClipsEnvironment”);

rb_define_module_function(ClipsEnvironment, “create_environment”, create_clips_environment, 0);

rb_define_module_function(ClipsEnvironment, “load_rules_file”, load_rules_file, 2);

}

“`

load_rules_file函数接受两个参数,即环境的指针和规则文件名。 该函数在Clips环境中加载了规则文件。 如果加载失败,则会抛出一个错误消息。

最后,我们需要编写一个函数来运行Clips规则引擎。

“`c

static VALUE run_clips_rules(VALUE self, VALUE clipsEnvironment) {

Environment* env = (Environment*)clipsEnvironment;

int runStatus = Run(env, -1L);

if (!runStatus) {

VALUE errorMessage = rb_str_new2(“Failed to run Clips rules”);

rb_exc_raise(errorMessage);

}

return Qnil;

}

void Init_clips() {

ClipsEnvironment = rb_define_module(“ClipsEnvironment”);

rb_define_module_function(ClipsEnvironment, “create_environment”, create_clips_environment, 0);

rb_define_module_function(ClipsEnvironment, “load_rules_file”, load_rules_file, 2);

rb_define_module_function(ClipsEnvironment, “run_clips_rules”, run_clips_rules, 1);

}

“`

run_clips_rules函数接受一个环境指针参数。 然后,它在传递-1L的情况下开始运行规则引擎。 如果运行失败,则会抛出一个错误消息。

现在,我们已经编写了所有必需的C函数,现在是时候在Ruby中测试它们了:

“`ruby

require ‘clips’

env = ClipsEnvironment.create_environment

env.load_rules_file(‘rules.clp’)

env.run_clips_rules

“`

以上代码将创建一个名为ClipsEnvironment的模块。 然后它将创建一个新的环境。

接下来,它将加载一个名为“rules.clp”的规则文件。 最后,它将启动Clips规则引擎并开始执行规则。

在这篇文章中,我们已经讨论了如何使用C扩展程序在Ruby中使用Clips规则引擎的所有基础知识。 我们已经创建了一个简单的API,它可以让我们从Ruby中创建一个环境,加载规则文件和启动规则引擎。 因此,我们可以在Ruby中利用Clips强大的规则引擎功能,从而扩展我们的应用程序。

详情参考

了解更多有趣的事情:https://blog.ds3783.com/