Re: Loading database from string (C API)
Jan Wielemaker <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <[email protected]> |
On 12/11/2013 02:19 PM, Edd Barrett wrote:
> Hi Jan,
>
> On Fri, Dec 06, 2013 at 02:49:16PM +0000, Edd Barrett wrote:
>>> So, the question becomes how to get a Prolog stream from a C string.
>>> You can do that using the stream API defined in SWI-Stream.h but still
>>> undocumented. What you want is something like below. The default
>>> encoding is ISO Latin 1. See SWI-Stream.h for other values.
>>>
>>> int
>>> open_stream(char *s, term_t t)
>>> { IOSTREAM *stream;
>>>
>>> stream = Sopen_string(NULL, s, strlen(s), "r");
>>> stream->encoding = ENC_UTF8;
>>>
>>> return PL_unify_stream(t, stream);
>>> }
>>
>> Thanks Jan.
>>
>> Hopefully Python's CFFI will allow me to write my own C functions (up
>> until now I have just been calling yours in libpl). If not, I can build
>> a shared object with this stub in.
>
> I have integrated this function into my work, but I immediately started
> getting strange behaviour. After some debugging, I think this stems from
> the identity of the stream itself. Let me demonstrate with a small C
> program:
>
> ---8<---
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
> #include <SWI-Prolog.h>
> #include <SWI-Stream.h>
>
> int
> open_stream(char *s, term_t t)
> {
> IOSTREAM *stream;
>
> stream = Sopen_string(NULL, s, strlen(s), "r");
> stream->encoding = ENC_UTF8;
>
> return PL_unify_stream(t, stream);
> }
>
> int
> main(int argc, char **argv)
> {
> term_t t;
>
> printf("Init\n");
> if (PL_initialise(argc, argv) != 1) {
> printf("Failed to initialise\n");
> PL_halt(1);
> }
>
> t = PL_new_term_ref();
> if ((open_stream("f(1, 2, 3).", t)) != TRUE) {
> printf("Something went wrong with open_stream\n");
> PL_halt(1);
> }
>
> printf("Is atom: %d\n", PL_is_atom(t));
> printf("Stream Type: %d\n", PL_term_type(t));
> printf("Atom Type: %d\n", PL_ATOM);
>
> printf("Halt\n");
> PL_halt(0);
>
> return (EXIT_SUCCESS);
> }
> ---8<---
>
>
> I can't find any documentation on PL_unify_stream; I assume it returns
> TRUE on success? Anyway, this program prints:
>
> ---8<---
> ...
> Is atom: 0
> Stream Type: 2
> Atom Type: 2
> Halt
> ---8<---
>
> So the stream reports itself as *not* an atom according to PL_is_atom()
> (since the return value was not non-zero), but then when asked for its exact
> type via PL_term_type() it says it is an atom. Who does this stream guy
> think he is?
>
> Either my mistake, a bug, or the stream is a special term?
It is a bug in PL_term_type(). This function is not very popular and
(thus) poorly maintained. Stream handles are `blobs'. Blob is
SWI-Prolog's internal super-type for shared symbols. Atoms are
just a sub-type thereof. Some examples:
1 ?- open_null_stream(X), blob(X, T).
X = <stream>(0xe4d880),
T = stream.
2 ?- asserta(a, Ref), blob(Ref, T).
Ref = <clause>(0x11298e0),
T = clause.
I'll fix PL_term_type()
Cheers --- Jan