Hi all,
I’m trying to write a generic c++ non-deterministic predicate, but have no idea about how to transfer the context. What I’ve tried always causes crash:(
%mycall.pl
:- module(mycall, [mycall/1]).
:- use_foreign_library('./mycall.dylib').
:- meta_predicate
mycall(0).
//mycall.cpp
#define PROLOG_MODULE "mycall"
#include <SWI-cpp.h>
#include <iostream>
using namespace std;
struct RetryContext {
PlTerm term;
PlTermv termv;
PlQuery query;
RetryContext(PlTerm const &t) : term(t), termv{term}, query("call", termv) {}
};
PREDICATE_NONDET(mycall, 1) {
int ctl = PL_foreign_control(handle);
int ret = 0;
RetryContext *rcp = nullptr;
switch (ctl) {
case PL_FIRST_CALL:
cout << "first call\n";
rcp = new RetryContext(A1);
ret = rcp->query.next_solution();
if (!ret)
goto out;
PL_retry_address(rcp);
case PL_REDO:
cout << "redo\n";
rcp = (RetryContext *)PL_foreign_context_address(handle);
ret = rcp->query.next_solution();
if (!ret)
goto out;
PL_retry_address(rcp);
case PL_PRUNED:
cout << "pruned\n";
rcp = (RetryContext *)PL_foreign_context_address(handle);
delete rcp;
return TRUE;
}
out:
cout << "out\n";
if (rcp)
delete rcp;
return ret ? TRUE : FALSE;
}
laowang@bogon test % clang++ --std=c++17 -I/usr/local/lib/swipl/include -L/usr/local/lib/swipl/lib/x86_64-darwin -lswipl -shared -o mycall.dylib mycall.cpp
laowang@bogon test % swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.9)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- use_module(mycall).
true.
?- assert(test(a)).
true.
?- mycall(test(X)).
first call
X = a.
SWI-Prolog [thread 1 (main) at Sat Dec 7 16:36:01 2019]: received fatal signal 11 (segv)
C-stack trace labeled “crash”:
[0] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(save_backtrace+0x62) [0x106434042]
[1] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(print_c_backtrace+0x15) [0x106434915]
[2] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(sigCrashHandler+0xf4) [0x106434824]
[3] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(dispatch_signal+0x41c) [0x10639571c]
[4] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(pl_signal_handler+0x15) [0x106398155]
[5] /usr/lib/system/libsystem_platform.dylib(_sigtramp+0x1d) [0x7fff67626b1d]
[6] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(releaseStream+0x26) [0x1063fe966]
[7] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(query_loop+0xd5) [0x10636f235]
[8] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(prologToplevel+0x7a) [0x10636fd7a]
[9] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/lib/swipl/lib/x86_64-darwin/libswipl.8.1.9.dylib(PL_toplevel+0x21) [0x10630a451]
[10] /usr/local/Cellar/swi-prolog/HEAD-ad9b759/libexec/bin/swipl(main+0x42) [0x1062d5f52]
[11] /usr/lib/system/libdyld.dylib(start+0x1) [0x7fff674252e5]
Running on_halt hooks with status 139
Killing 71566 with default signal handlers
zsh: segmentation fault swipl
laowang@bogon test % swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.9)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- use_module(’./mycall.pl’).
true.
?- assert(test(a)).
true.
?- assert(test(b)).
true.
?- mycall(test(X)).
first call
X = a ;
laowang@bogon test %
I’ll greatly appreciate any helps!
Arthur Wang