Does anyone know how to make a foreign predicate, written in C, fail or provide backtrack points?
Thanks, John
On Sat, Jan 19, 2013 at 7:35 PM, mcculloch <mccullochj(a)att.net> wrote:
Does anyone know how to make a foreign predicate, written in C, fail or provide backtrack points?
Dear John,
there exists two ways in Ciao to make a foreign predicate:
- low-level user interface (which allows direct access to the underlying virtual machine definitions) - high-level user interface (which uses assertions to map C functions as predicates)
Currently, only the first one allows failure or creation of choicepoints, but we discourage using it, since it is mostly undocumented, error prone, and hard to maintain.
However, you can simulate both failure and choice point creation using a Prolog wrapper. E.g., if check_foo_c/2 is a check written in C which returns '0' or '1' in its second argument, then you can write:
check_foo(X) :- check_foo_c(X, R), R = 1.
which maps the '0' result to a failure. A similar technique can be used to write nondeterministic programs using pieces in C.
If your program can be decomposed in such a way, then this may be a solution. If not, can you provide us at least some pseudo-code? We'll try to find the best solution or implement the missing functionality.
Cheers,
Thanks Jose. I've decided to reduce my C usage to only what is necessary and use Prolog whereever possible.
But, I really am trying to interface Ciao to a system that has a C driver library. The system is written in C++ and has a C++ driver library that is more efficient and otherwise better. I have two more questions:
1) Can foreign C predicates be in a library file or do they have to be compiled by ciaoc along with the prolog code? 2) Has anyone successfully used C++ for foreign code with ciao and what did they do to make it work?
Thanks again, John
Jose Morales-3 wrote:
On Sat, Jan 19, 2013 at 7:35 PM, mcculloch <mccullochj(a)att.net> wrote:
Does anyone know how to make a foreign predicate, written in C, fail or provide backtrack points?
Dear John,
there exists two ways in Ciao to make a foreign predicate:
- low-level user interface (which allows direct access to the underlying virtual machine definitions)
- high-level user interface (which uses assertions to map C functions as predicates)
Currently, only the first one allows failure or creation of choicepoints, but we discourage using it, since it is mostly undocumented, error prone, and hard to maintain.
However, you can simulate both failure and choice point creation using a Prolog wrapper. E.g., if check_foo_c/2 is a check written in C which returns '0' or '1' in its second argument, then you can write:
check_foo(X) :- check_foo_c(X, R), R = 1.
which maps the '0' result to a failure. A similar technique can be used to write nondeterministic programs using pieces in C.
If your program can be decomposed in such a way, then this may be a solution. If not, can you provide us at least some pseudo-code? We'll try to find the best solution or implement the missing functionality.
Cheers,
-- Jose
Ciao-users mailing list Ciao-users(a)clip.dia.fi.upm.es http://clip.dia.fi.upm.es/cgi-bin/mailman/listinfo/ciao-users
Hi John,
mcculloch wrote:
- Can foreign C predicates be in a library file or do they have to be
compiled by ciaoc along with the prolog code?
In ciao, foreign C predicates can be in a library file. See for example, the Mathematical functions example in the documentation of the foreign interface. http://ciao-lang.org/docs/ciao/foreign_interface_doc.html
- Has anyone successfully used C++ for foreign code with ciao and what did
they do to make it work?
Yes. In fact the high level C interface have been developed for (but not only) interfacing ciao with the Parma Polyhedra Library (ppl) a constraint library written in C++.
Unfortunately, ppl is pretty difficult to link with ciao because of some sensitive dependencies between gmp, ppl, ciao, the target architecture, and the compiler that compile/link everything.
Nonetheless ppl is maybe not the better example for you because it is built on the top of a common interface for different Prologs (Ciao, GNU, SICStus, SWI, XSB, YAP). This common interface uses therefore complex abstraction for the way the different systems interface with C/C++.
The simplest idea to interface Ciao and C++ would be to write C functions (functions prefixed by 'extern "C"' in the C++ code) that wrap calls from prolog to C++. Then C++ object could be casted as addresses.
I just included in the documentation of the foreign interface an example of the interface with C++ . But because Ciao web site is currently not generated, I join the example here. Note that to be able to run, the example needs a 32bits version of GNU Standard C++ Library (which is not always installed by default on 64 bits Linux).
Cheers,
Remy
Either way one looks at it, it would be more work to use C++ than to just use C and put up with the poor documentation for the mongoDB C driver. Besides, the C++ documentation is only marginally better.
I toyed with the idea of using couchDB instead of mongoDB, but, in the end, it seems easier to use BSON than JSON.
Thanks, John
Remy Haemmerle-2 wrote:
Hi John,
mcculloch wrote:
- Can foreign C predicates be in a library file or do they have to be
compiled by ciaoc along with the prolog code?
In ciao, foreign C predicates can be in a library file. See for example, the Mathematical functions example in the documentation of the foreign interface. http://ciao-lang.org/docs/ciao/foreign_interface_doc.html
- Has anyone successfully used C++ for foreign code with ciao and what
did they do to make it work?
Yes. In fact the high level C interface have been developed for (but not only) interfacing ciao with the Parma Polyhedra Library (ppl) a constraint library written in C++.
Unfortunately, ppl is pretty difficult to link with ciao because of some sensitive dependencies between gmp, ppl, ciao, the target architecture, and the compiler that compile/link everything.
Nonetheless ppl is maybe not the better example for you because it is built on the top of a common interface for different Prologs (Ciao, GNU, SICStus, SWI, XSB, YAP). This common interface uses therefore complex abstraction for the way the different systems interface with C/C++.
The simplest idea to interface Ciao and C++ would be to write C functions (functions prefixed by 'extern "C"' in the C++ code) that wrap calls from prolog to C++. Then C++ object could be casted as addresses.
I just included in the documentation of the foreign interface an example of the interface with C++ . But because Ciao web site is currently not generated, I join the example here. Note that to be able to run, the example needs a 32bits version of GNU Standard C++ Library (which is not always installed by default on 64 bits Linux).
Cheers,
Remy
#include <iostream> #include <stack> using namespace std;
typedef stack<int> ciao_stack;
extern "C" void * ciao_stack_new() { return (void*) new ciao_stack; }
extern "C" void ciao_stack_delete(void * S) { delete ((ciao_stack *) S); }
extern "C" int ciao_stack_size(void * S) { return (((ciao_stack *) S)->size()); }
extern "C" void ciao_stack_push(void * S, int v) { ((ciao_stack *) S)->push(v); }
extern "C" void ciao_stack_pop(void * S) { ((ciao_stack *) S)->pop(); }
extern "C" int ciao_stack_top(void * S) { return ((ciao_stack *) S)->top(); }
:- module(cc_stack, [cc_stack_new/1, cc_stack_size/2, cc_stack_push/2, cc_stack_pop/1, cc_stack_top/2], [foreign_interface, assertions]).
:- use_module(library(odd), [undo/1]).
:- true pred ciao_stack_new(go(Stack)) :: address
- (foreign, returns(Stack)).
:- true pred ciao_stack_delete(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_size(in(_Stack), go(Size)) :: (address * int)
- (foreign, returns(Size)).
:- true pred ciao_stack_push(in(_Stack), in(_Value)) :: (address * int)
- foreign.
:- true pred ciao_stack_pop(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_top(in(_Stack), go(Value)) :: (address * int)
- (foreign, returns(Value)).
cc_stack_new(ciao_stack(X)) :- ciao_stack_new(X), % stack are deallocate on backtrack. undo(ciao_stack_delete(X)).
cc_stack_size(ciao_stack(X), Size):- ciao_stack_size(X, Size).
cc_stack_push(ciao_stack(X), I):- ciao_stack_push(X, I).
cc_stack_pop(ciao_stack(X)):- ( ciao_stack_size(X, Size), Size > 0 -> ciao_stack_pop(X) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
cc_stack_top(ciao_stack(X), Int):- ( ciao_stack_size(X, Size), Size > 0 -> ciao_stack_top(X, Int) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
:- use_foreign_library('stdc++'). :- use_foreign_source('cc_stack.cc').
Ciao-users mailing list Ciao-users(a)clip.dia.fi.upm.es http://clip.dia.fi.upm.es/cgi-bin/mailman/listinfo/ciao-users
I am on a pure 32 bit Ubuntu 12.04 system now and made a test program, but I can't get it to work. Here's what I did
===========start============== john(a)laptop01:~/cpp_test$ more cpp_test.pl :- module(cpp_test,main/0,[foreign_interface,assertions]).
:- true pred test_cpp_pred :: foreign.
:- use_foreign_library(['stdc++']). :- use_foreign_source('test_pred.cpp').
main :- test_cpp_pred.
john(a)laptop01:~/cpp_test$ more test_pred.cpp #include <iostream> #include <ciao_prolog.h>
extern "C" void test_cpp_pred() { std::cout << "Works Good!\n"; }
john(a)laptop01:~/cpp_test$ ciaoc cpp_test.pl
john(a)laptop01:~/cpp_test$ ./cpp_test
{ERROR: No handle found for thrown error error(existence_error(procedure,/(cpp_test:test_cpp_pred,0)),/(cpp_test:test_cpp_pred,0))} ============end=================
As you can see, something is not right here. Any ideas?
I added "assertions" because the example had it. I don't know if it is necessary, but removing it doesn't change anything.
Thanks, John
Remy Haemmerle-2 wrote:
Hi John,
mcculloch wrote:
- Can foreign C predicates be in a library file or do they have to be
compiled by ciaoc along with the prolog code?
In ciao, foreign C predicates can be in a library file. See for example, the Mathematical functions example in the documentation of the foreign interface. http://ciao-lang.org/docs/ciao/foreign_interface_doc.html
- Has anyone successfully used C++ for foreign code with ciao and what
did they do to make it work?
Yes. In fact the high level C interface have been developed for (but not only) interfacing ciao with the Parma Polyhedra Library (ppl) a constraint library written in C++.
Unfortunately, ppl is pretty difficult to link with ciao because of some sensitive dependencies between gmp, ppl, ciao, the target architecture, and the compiler that compile/link everything.
Nonetheless ppl is maybe not the better example for you because it is built on the top of a common interface for different Prologs (Ciao, GNU, SICStus, SWI, XSB, YAP). This common interface uses therefore complex abstraction for the way the different systems interface with C/C++.
The simplest idea to interface Ciao and C++ would be to write C functions (functions prefixed by 'extern "C"' in the C++ code) that wrap calls from prolog to C++. Then C++ object could be casted as addresses.
I just included in the documentation of the foreign interface an example of the interface with C++ . But because Ciao web site is currently not generated, I join the example here. Note that to be able to run, the example needs a 32bits version of GNU Standard C++ Library (which is not always installed by default on 64 bits Linux).
Cheers,
Remy
#include <iostream> #include <stack> using namespace std;
typedef stack<int> ciao_stack;
extern "C" void * ciao_stack_new() { return (void*) new ciao_stack; }
extern "C" void ciao_stack_delete(void * S) { delete ((ciao_stack *) S); }
extern "C" int ciao_stack_size(void * S) { return (((ciao_stack *) S)->size()); }
extern "C" void ciao_stack_push(void * S, int v) { ((ciao_stack *) S)->push(v); }
extern "C" void ciao_stack_pop(void * S) { ((ciao_stack *) S)->pop(); }
extern "C" int ciao_stack_top(void * S) { return ((ciao_stack *) S)->top(); }
:- module(cc_stack, [cc_stack_new/1, cc_stack_size/2, cc_stack_push/2, cc_stack_pop/1, cc_stack_top/2], [foreign_interface, assertions]).
:- use_module(library(odd), [undo/1]).
:- true pred ciao_stack_new(go(Stack)) :: address
- (foreign, returns(Stack)).
:- true pred ciao_stack_delete(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_size(in(_Stack), go(Size)) :: (address * int)
- (foreign, returns(Size)).
:- true pred ciao_stack_push(in(_Stack), in(_Value)) :: (address * int)
- foreign.
:- true pred ciao_stack_pop(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_top(in(_Stack), go(Value)) :: (address * int)
- (foreign, returns(Value)).
cc_stack_new(ciao_stack(X)) :- ciao_stack_new(X), % stack are deallocate on backtrack. undo(ciao_stack_delete(X)).
cc_stack_size(ciao_stack(X), Size):- ciao_stack_size(X, Size).
cc_stack_push(ciao_stack(X), I):- ciao_stack_push(X, I).
cc_stack_pop(ciao_stack(X)):- ( ciao_stack_size(X, Size), Size > 0 -> ciao_stack_pop(X) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
cc_stack_top(ciao_stack(X), Int):- ( ciao_stack_size(X, Size), Size > 0 -> ciao_stack_top(X, Int) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
:- use_foreign_library('stdc++'). :- use_foreign_source('cc_stack.cc').
Ciao-users mailing list Ciao-users(a)clip.dia.fi.upm.es http://clip.dia.fi.upm.es/cgi-bin/mailman/listinfo/ciao-users
Hi John,
The problem is in the assertion:
:- true pred test_cpp_pred :: foreign.
The correct syntax is:
:- true pred test_cpp_pred + foreign.
Cheers,
Remy
mcculloch wrote:
I am on a pure 32 bit Ubuntu 12.04 system now and made a test program, but I can't get it to work. Here's what I did
===========start============== john(a)laptop01:~/cpp_test$ more cpp_test.pl :- module(cpp_test,main/0,[foreign_interface,assertions]).
:- true pred test_cpp_pred :: foreign.
:- use_foreign_library(['stdc++']). :- use_foreign_source('test_pred.cpp').
main :- test_cpp_pred.
john(a)laptop01:~/cpp_test$ more test_pred.cpp #include<iostream> #include<ciao_prolog.h>
extern "C" void test_cpp_pred() { std::cout<< "Works Good!\n"; }
john(a)laptop01:~/cpp_test$ ciaoc cpp_test.pl
john(a)laptop01:~/cpp_test$ ./cpp_test
{ERROR: No handle found for thrown error error(existence_error(procedure,/(cpp_test:test_cpp_pred,0)),/(cpp_test:test_cpp_pred,0))} ============end=================
As you can see, something is not right here. Any ideas?
I added "assertions" because the example had it. I don't know if it is necessary, but removing it doesn't change anything.
Thanks, John
Remy Haemmerle-2 wrote:
Hi John,
mcculloch wrote:
- Can foreign C predicates be in a library file or do they have to be
compiled by ciaoc along with the prolog code?
In ciao, foreign C predicates can be in a library file. See for example, the Mathematical functions example in the documentation of the foreign interface. http://ciao-lang.org/docs/ciao/foreign_interface_doc.html
- Has anyone successfully used C++ for foreign code with ciao and what
did they do to make it work?
Yes. In fact the high level C interface have been developed for (but not only) interfacing ciao with the Parma Polyhedra Library (ppl) a constraint library written in C++.
Unfortunately, ppl is pretty difficult to link with ciao because of some sensitive dependencies between gmp, ppl, ciao, the target architecture, and the compiler that compile/link everything.
Nonetheless ppl is maybe not the better example for you because it is built on the top of a common interface for different Prologs (Ciao, GNU, SICStus, SWI, XSB, YAP). This common interface uses therefore complex abstraction for the way the different systems interface with C/C++.
The simplest idea to interface Ciao and C++ would be to write C functions (functions prefixed by 'extern "C"' in the C++ code) that wrap calls from prolog to C++. Then C++ object could be casted as addresses.
I just included in the documentation of the foreign interface an example of the interface with C++ . But because Ciao web site is currently not generated, I join the example here. Note that to be able to run, the example needs a 32bits version of GNU Standard C++ Library (which is not always installed by default on 64 bits Linux).
Cheers,
Remy
#include<iostream> #include<stack> using namespace std;
typedef stack<int> ciao_stack;
extern "C" void * ciao_stack_new() { return (void*) new ciao_stack; }
extern "C" void ciao_stack_delete(void * S) { delete ((ciao_stack *) S); }
extern "C" int ciao_stack_size(void * S) { return (((ciao_stack *) S)->size()); }
extern "C" void ciao_stack_push(void * S, int v) { ((ciao_stack *) S)->push(v); }
extern "C" void ciao_stack_pop(void * S) { ((ciao_stack *) S)->pop(); }
extern "C" int ciao_stack_top(void * S) { return ((ciao_stack *) S)->top(); }
:- module(cc_stack, [cc_stack_new/1, cc_stack_size/2, cc_stack_push/2, cc_stack_pop/1, cc_stack_top/2], [foreign_interface, assertions]).
:- use_module(library(odd), [undo/1]).
:- true pred ciao_stack_new(go(Stack)) :: address
- (foreign, returns(Stack)).
:- true pred ciao_stack_delete(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_size(in(_Stack), go(Size)) :: (address * int)
- (foreign, returns(Size)).
:- true pred ciao_stack_push(in(_Stack), in(_Value)) :: (address * int)
- foreign.
:- true pred ciao_stack_pop(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_top(in(_Stack), go(Value)) :: (address * int)
- (foreign, returns(Value)).
cc_stack_new(ciao_stack(X)) :- ciao_stack_new(X), % stack are deallocate on backtrack. undo(ciao_stack_delete(X)).
cc_stack_size(ciao_stack(X), Size):- ciao_stack_size(X, Size).
cc_stack_push(ciao_stack(X), I):- ciao_stack_push(X, I).
cc_stack_pop(ciao_stack(X)):- ( ciao_stack_size(X, Size), Size> 0 -> ciao_stack_pop(X) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
cc_stack_top(ciao_stack(X), Int):- ( ciao_stack_size(X, Size), Size> 0 -> ciao_stack_top(X, Int) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
:- use_foreign_library('stdc++'). :- use_foreign_source('cc_stack.cc').
Ciao-users mailing list Ciao-users(a)clip.dia.fi.upm.es http://clip.dia.fi.upm.es/cgi-bin/mailman/listinfo/ciao-users
Thanks Remy!
I now have a test program successfully connecting a ciao prolog program to mongoDB via its C++ driver which uses classes.
I plan on extending it as far as I can.
John
Remy Haemmerle-2 wrote:
Hi John,
The problem is in the assertion:
:- true pred test_cpp_pred :: foreign.
The correct syntax is:
:- true pred test_cpp_pred + foreign.
Cheers,
Remy
mcculloch wrote:
I am on a pure 32 bit Ubuntu 12.04 system now and made a test program, but I can't get it to work. Here's what I did
===========start============== john(a)laptop01:~/cpp_test$ more cpp_test.pl :- module(cpp_test,main/0,[foreign_interface,assertions]).
:- true pred test_cpp_pred :: foreign.
:- use_foreign_library(['stdc++']). :- use_foreign_source('test_pred.cpp').
main :- test_cpp_pred.
john(a)laptop01:~/cpp_test$ more test_pred.cpp #include<iostream> #include<ciao_prolog.h>
extern "C" void test_cpp_pred() { std::cout<< "Works Good!\n"; }
john(a)laptop01:~/cpp_test$ ciaoc cpp_test.pl
john(a)laptop01:~/cpp_test$ ./cpp_test
{ERROR: No handle found for thrown error error(existence_error(procedure,/(cpp_test:test_cpp_pred,0)),/(cpp_test:test_cpp_pred,0))} ============end=================
As you can see, something is not right here. Any ideas?
I added "assertions" because the example had it. I don't know if it is necessary, but removing it doesn't change anything.
Thanks, John
Remy Haemmerle-2 wrote:
Hi John,
mcculloch wrote:
- Can foreign C predicates be in a library file or do they have to be
compiled by ciaoc along with the prolog code?
In ciao, foreign C predicates can be in a library file. See for example, the Mathematical functions example in the documentation of the foreign interface. http://ciao-lang.org/docs/ciao/foreign_interface_doc.html
- Has anyone successfully used C++ for foreign code with ciao and
what did they do to make it work?
Yes. In fact the high level C interface have been developed for (but not only) interfacing ciao with the Parma Polyhedra Library (ppl) a constraint library written in C++.
Unfortunately, ppl is pretty difficult to link with ciao because of some sensitive dependencies between gmp, ppl, ciao, the target architecture, and the compiler that compile/link everything.
Nonetheless ppl is maybe not the better example for you because it is built on the top of a common interface for different Prologs (Ciao, GNU, SICStus, SWI, XSB, YAP). This common interface uses therefore complex abstraction for the way the different systems interface with C/C++.
The simplest idea to interface Ciao and C++ would be to write C functions (functions prefixed by 'extern "C"' in the C++ code) that wrap calls from prolog to C++. Then C++ object could be casted as addresses.
I just included in the documentation of the foreign interface an example of the interface with C++ . But because Ciao web site is currently not generated, I join the example here. Note that to be able to run, the example needs a 32bits version of GNU Standard C++ Library (which is not always installed by default on 64 bits Linux).
Cheers,
Remy
#include<iostream> #include<stack> using namespace std;
typedef stack<int> ciao_stack;
extern "C" void * ciao_stack_new() { return (void*) new ciao_stack; }
extern "C" void ciao_stack_delete(void * S) { delete ((ciao_stack *) S); }
extern "C" int ciao_stack_size(void * S) { return (((ciao_stack *) S)->size()); }
extern "C" void ciao_stack_push(void * S, int v) { ((ciao_stack *) S)->push(v); }
extern "C" void ciao_stack_pop(void * S) { ((ciao_stack *) S)->pop(); }
extern "C" int ciao_stack_top(void * S) { return ((ciao_stack *) S)->top(); }
:- module(cc_stack, [cc_stack_new/1, cc_stack_size/2, cc_stack_push/2, cc_stack_pop/1, cc_stack_top/2], [foreign_interface, assertions]).
:- use_module(library(odd), [undo/1]).
:- true pred ciao_stack_new(go(Stack)) :: address
- (foreign, returns(Stack)).
:- true pred ciao_stack_delete(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_size(in(_Stack), go(Size)) :: (address * int)
- (foreign, returns(Size)).
:- true pred ciao_stack_push(in(_Stack), in(_Value)) :: (address * int)
- foreign.
:- true pred ciao_stack_pop(in(_Stack)) :: address
- foreign.
:- true pred ciao_stack_top(in(_Stack), go(Value)) :: (address * int)
- (foreign, returns(Value)).
cc_stack_new(ciao_stack(X)) :- ciao_stack_new(X), % stack are deallocate on backtrack. undo(ciao_stack_delete(X)).
cc_stack_size(ciao_stack(X), Size):- ciao_stack_size(X, Size).
cc_stack_push(ciao_stack(X), I):- ciao_stack_push(X, I).
cc_stack_pop(ciao_stack(X)):- ( ciao_stack_size(X, Size), Size> 0 -> ciao_stack_pop(X) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
cc_stack_top(ciao_stack(X), Int):- ( ciao_stack_size(X, Size), Size> 0 -> ciao_stack_top(X, Int) ; throw(error(empty_cc_stack, cc_stack_pop/1-1)) ).
:- use_foreign_library('stdc++'). :- use_foreign_source('cc_stack.cc').
Ciao-users mailing list Ciao-users(a)clip.dia.fi.upm.es http://clip.dia.fi.upm.es/cgi-bin/mailman/listinfo/ciao-users
Ciao-users mailing list Ciao-users(a)clip.dia.fi.upm.es http://clip.dia.fi.upm.es/cgi-bin/mailman/listinfo/ciao-users