有没有什么合理的方法可以在 C 程序中嵌入 Prolog 解释器?

Eth*_*gue 8 c interpreter prolog

我想在 C 程序中嵌入 Prolog 解释器,以便它可以用于评估业务规则。

SWI-Prolog 和 GNU Prolog 似乎都暗示有这样的功能,但两者似乎也需要使用自己的编译器和链接器才能这样做,并且没有任何明确的例子或这种用法的文档 -而不是提供常规库来使用和清除文档。

我正在寻找的是一个库,它的行为类似于 Python 和 Lua 可以嵌入到 C 程序中的方式,例如:

// Setup
PrologContext context = plNewContext();
plConsult(context, "businessRules.pl");

// Later in the program
if (plEvaluate(context, "can_view_page(%a)", path)) { ...
Run Code Online (Sandbox Code Playgroud)

raj*_*kar 6

这是一个使用between/3.

#include <stdio.h>
#include <SWI-Prolog.h>

int main()
{
  char *argv[] = {"hello", "-q"};
  PL_initialise(2, argv);

  term_t a = PL_new_term_refs(3);
  PL_put_integer(a, 11); // First argument to between/3
  PL_put_integer(a+1, 17); // Second argument to between/3

  static predicate_t p;
  if(!p)
    p = PL_predicate("between", 3, NULL) ; // predicate between/3
  
  qid_t q = PL_open_query(NULL, PL_Q_NORMAL, p, a);
  int tmp;
  while(PL_next_solution(q)==TRUE){
    PL_get_integer(a+2, &tmp); // Third argument to between/3
    printf("%d\n", tmp);
  }
  PL_close_query(q);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用编译swipl-ld并执行

swipl-ld -o between between.c
./between
11
12
13
14
15
16
17
Run Code Online (Sandbox Code Playgroud)

另一个例子,如果你想加载一个文件然后进行查询。

#include <stdio.h>
#include <SWI-Prolog.h>

void consult_file(const char* filename){
  /* PL_initialse before calling. */
  predicate_t p = PL_predicate("consult", 1, NULL);
  term_t a = PL_new_term_ref();
  PL_put_atom_chars(a, filename);
  PL_call_predicate(NULL, PL_Q_NORMAL, p, a);
}

int main()
{
  char* argv[] = {"consult_file", "-q"};
  PL_initialise(2, argv);
  consult_file("digits.pl"); /* Load prolog file */

  static predicate_t p;
  /* third argument is module name if the predicate is in one.*/
  if(!p) p= PL_predicate("digit", 1, NULL); 
  int tmp; term_t a = PL_new_term_ref();
  qid_t q = PL_open_query(NULL, PL_Q_NORMAL, p, a);
  while(PL_next_solution(q)==TRUE){ /* All solutions */
    PL_get_integer(a, &tmp);
    printf("%d ", tmp);
  }

  return PL_halt(0);
}
Run Code Online (Sandbox Code Playgroud)

使用digits.pl如下文件,我们得到三个数字1 2 3 作为输出。

digit(1).
digit(2).
digit(3).
Run Code Online (Sandbox Code Playgroud)


Dav*_*fer 5

我不能代表 GNU Prolog,但 SWI-Prolog 绝对有详细的文档记录

请注意,各种 Prolog 实现都有自己特定的接口,没有任何标准化。ISO 标准什么也没说(仔细想想,实际上更好。这可能会是一团乱麻;似乎也没有人实施标准化模块方法)。

这项工作当然充满了无趣的实现细节,但这关于 C 的。决不需要特殊的编译器或链接器。

但有一种更酷的方法(即适应 2020 年以及 IT 实际工作方式的方法,即作为一组通信进程,每个进程专用于整个任务的一个域):创建一个单独的服务器进程,托管 Prolog 来回答查询, (一个 SWI-Prolog 引擎,“Pengine”)并通过 HTTP 从 C 编码的客户端进程访问它:Pengine。不过,没有关于从 C 程序设置 HTTP 交换的示例代码。这将取决于您的 HTTP 客户端库。