从 C/C++ 传递 EnvFunctionCall 实例地址
Passing EnvFunctionCall an instance address from C/C++
我想从 C++ 调用 CLIPS deffunction 并向其传递一个实例。我使用的是标准的 CLIPS 6.30 发行版(不是任何 C++ 绑定)。我目前正在使用以下定义:
(defclass CFAM (is-a USER))
(deffunction drop-cfam (?cfam)
(send ?cfam delete))
(definstances KNOWN_THINGS
(cfam-1 of CFAM))
我通过将我要删除的实例的实例地址传递给它,从 C++ 调用函数 drop-cfam
。
void* instancePtr = EnvFindInstance(clipsEnv,NULL,"cfam-1",false);
assert(EnvValidInstanceAddress(clipsEnv,instancePtr));
ostringstream args;
args << instancePtr;
cout << "Calling 'EnvFunctionCall for 'drop-cfam' w/ args: "<< args.str() << endl;
DATA_OBJECT callResult;
const bool callFailed = EnvFunctionCall(clipsEnv,"drop-cfam",args.str().c_str(),&callResult);
assert(!callFailed); // results in abort
const bool droppedCfam = static_cast<bool>(DOToInteger(callResult));
assert(droppedCfam);
指定行发生中止,同时终端window显示:
Calling 'EnvFunctionCall for 'drop-cfam' w/ args: 0x274c290
[MSGFUN1] No applicable primary message-handlers found for delete.
[PRCCODE4] Execution halted during the actions of deffunction drop-cfam.
最初,这表明我将(我认为是)实例地址传递给 drop-cfam
可能是不正确的。但是,在终端中测试表明这应该不是问题所在:
CLIPS> (reset)
CLIPS> (instances)
[initial-object] of INITIAL-OBJECT
[cfam-1] of CFAM
For a total of 2 instances.
CLIPS> (drop-cfam (instance-address [cfam-1]))
TRUE
CLIPS> (instances)
[initial-object] of INITIAL-OBJECT
For a total of 1 instance.
高级编程指南 (v6.30) 指出参数应作为字符串传递给 EnvFunctionCall
。该部分 (4.1.10) 没有指定对传递给 EnvFunctionCall
的数据类型的任何限制,也没有引用任何其他指定数据类型的词法形式的来源。我不确定我现在是否 可以 通过 EnvFunctionCall
传递实例地址,或者我的设计是否需要修改以避免它。
编辑/解决方法
我的设计中存在一个问题,我假设我的系统需要一个实例地址,而实际上它不需要。通过将实例名称传递给 EnvFunctionCall
而不是地址,可以实现此问题的预期行为,如下所示:
EnvFunctionCall(clipsEnv,"drop-cfam","[cfam-1]",&callResult);
与以下行为相同:
CLIPS> (reset)
CLIPS> (drop-cfam [cfam-1])
TRUE
我仍然会接受任何演示如何以词汇形式传递实例地址或描述为什么终端版本接受实例名称和实例地址的答案。
C 指针(包括实例、事实和外部地址)在 CLIPS 中没有词法表示,因此您不能直接指定它们。这既适用于解析字符串参数的 API 调用,也适用于终端命令和 CLIPS 代码。在执行过程中,地址可以动态绑定或从函数调用返回,这些值可以传递给函数。这就是在您的示例函数调用“(drop-cfam (instance-address [cfam-1]))”中从终端计算实例地址的方式。您可以使用 EnvEval 而不是 EnvFunctionCall 计算相同类型的表达式:
EnvEval(clipsEnv,"(drop-cfam (instance-address [cfam-1]))",&callResult);
我想从 C++ 调用 CLIPS deffunction 并向其传递一个实例。我使用的是标准的 CLIPS 6.30 发行版(不是任何 C++ 绑定)。我目前正在使用以下定义:
(defclass CFAM (is-a USER))
(deffunction drop-cfam (?cfam)
(send ?cfam delete))
(definstances KNOWN_THINGS
(cfam-1 of CFAM))
我通过将我要删除的实例的实例地址传递给它,从 C++ 调用函数 drop-cfam
。
void* instancePtr = EnvFindInstance(clipsEnv,NULL,"cfam-1",false);
assert(EnvValidInstanceAddress(clipsEnv,instancePtr));
ostringstream args;
args << instancePtr;
cout << "Calling 'EnvFunctionCall for 'drop-cfam' w/ args: "<< args.str() << endl;
DATA_OBJECT callResult;
const bool callFailed = EnvFunctionCall(clipsEnv,"drop-cfam",args.str().c_str(),&callResult);
assert(!callFailed); // results in abort
const bool droppedCfam = static_cast<bool>(DOToInteger(callResult));
assert(droppedCfam);
指定行发生中止,同时终端window显示:
Calling 'EnvFunctionCall for 'drop-cfam' w/ args: 0x274c290
[MSGFUN1] No applicable primary message-handlers found for delete.
[PRCCODE4] Execution halted during the actions of deffunction drop-cfam.
最初,这表明我将(我认为是)实例地址传递给 drop-cfam
可能是不正确的。但是,在终端中测试表明这应该不是问题所在:
CLIPS> (reset)
CLIPS> (instances)
[initial-object] of INITIAL-OBJECT
[cfam-1] of CFAM
For a total of 2 instances.
CLIPS> (drop-cfam (instance-address [cfam-1]))
TRUE
CLIPS> (instances)
[initial-object] of INITIAL-OBJECT
For a total of 1 instance.
高级编程指南 (v6.30) 指出参数应作为字符串传递给 EnvFunctionCall
。该部分 (4.1.10) 没有指定对传递给 EnvFunctionCall
的数据类型的任何限制,也没有引用任何其他指定数据类型的词法形式的来源。我不确定我现在是否 可以 通过 EnvFunctionCall
传递实例地址,或者我的设计是否需要修改以避免它。
编辑/解决方法
我的设计中存在一个问题,我假设我的系统需要一个实例地址,而实际上它不需要。通过将实例名称传递给 EnvFunctionCall
而不是地址,可以实现此问题的预期行为,如下所示:
EnvFunctionCall(clipsEnv,"drop-cfam","[cfam-1]",&callResult);
与以下行为相同:
CLIPS> (reset)
CLIPS> (drop-cfam [cfam-1])
TRUE
我仍然会接受任何演示如何以词汇形式传递实例地址或描述为什么终端版本接受实例名称和实例地址的答案。
C 指针(包括实例、事实和外部地址)在 CLIPS 中没有词法表示,因此您不能直接指定它们。这既适用于解析字符串参数的 API 调用,也适用于终端命令和 CLIPS 代码。在执行过程中,地址可以动态绑定或从函数调用返回,这些值可以传递给函数。这就是在您的示例函数调用“(drop-cfam (instance-address [cfam-1]))”中从终端计算实例地址的方式。您可以使用 EnvEval 而不是 EnvFunctionCall 计算相同类型的表达式:
EnvEval(clipsEnv,"(drop-cfam (instance-address [cfam-1]))",&callResult);