2016-08-22 41 views
0

我想从C++调用CLIPS deffunction并将它传递给一个实例。我正在使用标准的CLIPS 6.30发行版(不是任何C++绑定)。我目前正在与以下定义的工作:从C/C++传递EnvFunctionCall实例地址

(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); 

中止发生在指定的路线,而终端窗口显示:

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 

我还是会接受任何答案演示如何以词法形式传递实例地址或描述终端版本接受实例名称和实例地址的原因。

回答

0

对于C指针(其中包括实例,事实和外部地址),在CLIPS中没有词汇表示,所以不能直接指定它们。这既适用于解析字符串参数的API调用,也适用于终端命令和CLIPS代码。在执行期间,地址可以被动态绑定或从函数调用返回,并且这些值可以传递给函数。这就是在您的示例函数调用“(drop-cfam(instance-address [cfam-1]))”中从终端计算实例地址的方式。您可以使用EnvEval而不是EnvFunctionCall评估相同类型的表达式:

EnvEval(clipsEnv,"(drop-cfam (instance-address [cfam-1]))",&callResult);