[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

Help a Parisian documentarian with Eliza/c++ interface?

Jeff Shrager

9/7/2015 4:12:00 PM

I received the following request (slightly paraphrased):

---
I am a French director of documentaries for French public TV channel, and for theatrical/festival release, and video/multimedia artist. I plan to use the original Eliza (from http://el...) for a performance to be held in Paris. I've been studying Lisp for roughly a month and I understand the overall mechanics of Eliza. I have installed and tested the 1969 program successfully on os x using ecl. For the purpose of this performance, I have to modify the I/O to link it with an external user interface written in C++. For example, I might need a Lisp function passing the user sentence as a string, and returning Eliza reply as a string. I understand input happens via ratom function and the reader. As a start I tried replacing the read call in ratom by a read-from-string, but this is not working. Could you give me some hint, or point a direction in which I should proceed?
---

Someone who knows ecl, and esp. c++ (the latter would NOT be me!), could probably easily give this person a hand and possibly get credited in a French documentary (!); special bonus if you happen to live in Paris you could even attend the performance and see your handiwork in action!

I don't want to give out the person's identity in this public forum, but I'll be happy to make an introduction if you contact me via email.

Cheers,
'Jeff
7 Answers

Dimitri Fontaine

9/7/2015 6:06:00 PM

0

jshrager@gmail.com writes:
> successfully on os x using ecl. For the purpose of this performance, I have
> to modify the I/O to link it with an external user interface written in C++.

What about having the lisp program listen on a socket and answer there,
and have the C++ parts communicate there? Might be the easiest way outâ?¦

--
dim

Victor

9/9/2015 8:30:00 AM

0

?????????, 7 ??????? 2015 ?. 21:05:45 UTC+3 ?????????? Dimitri Fontaine ???????:
> js...r@gmail.com writes:
> > successfully on os x using ecl. For the purpose of this performance, I have
> > to modify the I/O to link it with an external user interface written in C++.
>
> What about having the lisp program listen on a socket and answer there,
> and have the C++ parts communicate there? Might be the easiest way out…

Are sockets really needed? What about starting the ECL process from the C++ application and redirecting stdin/stdout? Or using the named pipes will probably require only minor modifications for the applications both in Lisp and C++ (see http://www.linuxjournal.com/ar... ).

WBR,
Victor

Pascal J. Bourguignon

9/9/2015 3:36:00 PM

0

Vityok <bobbie@ua.fm> writes:

> понедÑ?лок, 7 веÑ?есня 2015 Ñ?. 21:05:45 UTC+3 коÑ?исÑ?Ñ?ваÑ? Dimitri Fontaine написав:
>> js...r@gmail.com writes:
>> > successfully on os x using ecl. For the purpose of this performance, I have
>> > to modify the I/O to link it with an external user interface written in C++.
>>
>> What about having the lisp program listen on a socket and answer there,
>> and have the C++ parts communicate there? Might be the easiest way outâ?¦
>
> Are sockets really needed? What about starting the ECL process from
> the C++ application and redirecting stdin/stdout? Or using the named
> pipes will probably require only minor modifications for the
> applications both in Lisp and C++ (see
> http://www.linuxjournal.com/ar... ).

Sockets, pipes, named pipes, it's all the same in the linux kernel.

On MacOSX, you can use popen(â?¦,"r+"); from the documentation this
shouldn't work on linux, since popen pipes are unidirectional on linux;
but they're bidirectional on MacOSX:

----(example.c++)--------------------------------------------------------
#include <string>
#include <iostream>
extern "C"{
#include <stdio.h>
#include <string.h>
}

void copy_output(FILE* eliza){
char buffer[4096];
int i=0;
while(1){
int ch=fgetc(eliza);
if(ch>=0){
buffer[i++]=ch;
}
if((ch<0)||(ch=='\n')){
buffer[i]='\0';
std::cout<<buffer;
i=0;
if(ch<0){
std::cout<<std::endl;
return;
}
continue;
}
if((i==1)&&(ch=='*')){
std::cout<<std::endl;
return;
}
if(i>=sizeof(buffer)-2){
buffer[i++]='\0';
std::cout<<buffer;
i=0;
}
}
}


int main(){
std::cout<<"Eliza wrapper"<<std::endl;
FILE* eliza=popen("ecl -norc -shell coselleliza1969and1972.lisp 2>/dev/null","r+");
if(eliza==0){
perror("popen");
return 1;
}
while(1){
copy_output(eliza);
std::cout<<"> "<<std::flush;
try_again:
char input[4096];
std::cin.getline(input,sizeof(input)-2);
if(std::cin.eof()||(strcmp(input,"exit")==0)||(strcmp(input,"quit")==0)){
break;
}
int len=strlen(input);
if(len==0){
goto try_again;
}
char last=input[len-1];
if(!((last=='.')||(last=='!')||(last=='?'))){
input[len]='.';
input[len+1]='\0';
}
fprintf(eliza,"%s\n",input);
fflush(eliza);
}
return 0;
}
--------------------------------------------------------------------------------


--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Kaz Kylheku

9/9/2015 3:47:00 PM

0

On 2015-09-09, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> Vityok <bobbie@ua.fm> writes:
>
>> понедÑ?лок, 7 веÑ?есня 2015 Ñ?. 21:05:45 UTC+3 коÑ?исÑ?Ñ?ваÑ? Dimitri Fontaine написав:
>>> js...r@gmail.com writes:
>>> > successfully on os x using ecl. For the purpose of this performance, I have
>>> > to modify the I/O to link it with an external user interface written in C++.
>>>
>>> What about having the lisp program listen on a socket and answer there,
>>> and have the C++ parts communicate there? Might be the easiest way outâ?¦
>>
>> Are sockets really needed? What about starting the ECL process from
>> the C++ application and redirecting stdin/stdout? Or using the named
>> pipes will probably require only minor modifications for the
>> applications both in Lisp and C++ (see
>> http://www.linuxjournal.com/ar... ).
>
> Sockets, pipes, named pipes, it's all the same in the linux kernel.
>
> On MacOSX, you can use popen(â?¦,"r+"); from the documentation this
> shouldn't work on linux, since popen pipes are unidirectional on linux;
> but they're bidirectional on MacOSX:

popen is unidirectional in POSIX, so this is an extension.

http://pubs.opengroup.org/onlinepubs/9699919799/functions/...

This is not a Linux thing.

The main reason is that the underlying pipes created by the pipe system
call are unidirectional, and implementations of the FILE stream in stdio
use a single file descriptor (and this implementation detail is revealed
in the API: POSIX has the fileno(stream) function to get the fd).

MacOS is probably using socketpair or some internal function to make
a two-directional pipe.

It seems quite useful for certain trivial cases where you don't have
to worry about deadlock. For instance, suppose that some program
accepts a small query command on standard input before producing output.
If the process reads its input its entirety before trying to produce output,
or else if the input query fits into the pipe, then there is no risk
of deadlock.

Pascal J. Bourguignon

9/9/2015 4:02:00 PM

0

Kaz Kylheku <kaz@kylheku.com> writes:

> On 2015-09-09, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>> Vityok <bobbie@ua.fm> writes:
>>
>>> понедÑ?лок, 7 веÑ?есня 2015 Ñ?. 21:05:45 UTC+3 коÑ?исÑ?Ñ?ваÑ? Dimitri Fontaine написав:
>>>> js...r@gmail.com writes:
>>>> > successfully on os x using ecl. For the purpose of this performance, I have
>>>> > to modify the I/O to link it with an external user interface written in C++.
>>>>
>>>> What about having the lisp program listen on a socket and answer there,
>>>> and have the C++ parts communicate there? Might be the easiest way outâ?¦
>>>
>>> Are sockets really needed? What about starting the ECL process from
>>> the C++ application and redirecting stdin/stdout? Or using the named
>>> pipes will probably require only minor modifications for the
>>> applications both in Lisp and C++ (see
>>> http://www.linuxjournal.com/ar... ).
>>
>> Sockets, pipes, named pipes, it's all the same in the linux kernel.
>>
>> On MacOSX, you can use popen(â?¦,"r+"); from the documentation this
>> shouldn't work on linux, since popen pipes are unidirectional on linux;
>> but they're bidirectional on MacOSX:
>
> popen is unidirectional in POSIX, so this is an extension.
>
> http://pubs.opengroup.org/onlinepubs/9699919799/functions/...
>
> This is not a Linux thing.
>
> The main reason is that the underlying pipes created by the pipe system
> call are unidirectional, and implementations of the FILE stream in stdio
> use a single file descriptor (and this implementation detail is revealed
> in the API: POSIX has the fileno(stream) function to get the fd).
>
> MacOS is probably using socketpair or some internal function to make
> a two-directional pipe.
>
> It seems quite useful for certain trivial cases where you don't have
> to worry about deadlock. For instance, suppose that some program
> accepts a small query command on standard input before producing output.
> If the process reads its input its entirety before trying to produce output,
> or else if the input query fits into the pipe, then there is no risk
> of deadlock.

AFAIK, you can still have two threads, one reading and one writing on
the same bidirectional pipe, or on two unidirectional pipes. So the
deadlock problem is the same in both cases, and can be solved the same
way in both cases.

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

smh

9/10/2015 1:47:00 PM

0

An implementer who is sufficiently unambitious can solve the entire problem much more simply, and entirely within the ANSI-CL standard, and using nothing beyond that on the C++ side, and using only a single thread on each side.

Observe that the two programs perform a strict ping-pong exchange. A sends a communication to B, then B sends a reply to A. No variation. Since the exchange involves a human and a keyboard, neither transmission rate not latency matters.

The two programs need only agree on two writable files, .../message and .../semaphore .

A creates, writes, and closes message, then creates, writes, and closes semaphore worth the single character A. B waits in a (sleep 1) loop until the semaphore file exists with the expected content. B reads and deletes both files, then creates, writes, and closes message, then creates semaphore containing the single character B, while A waits for the semaphore to exist with the proper content. ...

All this can be accomplished with just a few lines of code on the Lisp side and a ridiculously (but only proportionally) larger number of lines on the C++ side. Some error checking might be required, for insurance if the local filesystem prevent a file from being opened for input while still open for output.

Of course, both programs must run on the same host, or at least have access to a shared file system.

Madhu

10/1/2015 7:54:00 AM

0


* Kaz Kylheku <20150909083744.251@kylheku.com> :
Wrote on Wed, 9 Sep 2015 15:47:05 +0000 (UTC):

|> Sockets, pipes, named pipes, it's all the same in the linux kernel.
|>
|> On MacOSX, you can use popen(â?¦,"r+"); from the documentation this
|> shouldn't work on linux, since popen pipes are unidirectional on
|> linux; but they're bidirectional on MacOSX:
|
| popen is unidirectional in POSIX, so this is an extension.
|
| http://pubs.opengroup.org/onlinepubs/9699919799/functions/...
|
| This is not a Linux thing.

from popen(3) on some old freebsd

" Bidirectional functionality was added in FreeBSD 2.2.6."

| The main reason is that the underlying pipes created by the pipe
| system call are unidirectional, and implementations of the FILE stream
| in stdio use a single file descriptor (and this implementation detail
| is revealed in the API: POSIX has the fileno(stream) function to get
| the fd).
|
| MacOS is probably using socketpair or some internal function to make a
| two-directional pipe.

The first hit indicates that this is so:

http://github.com/Apple-FOSS-Mirror/Libc/raw/master/gen/FreeB...

Lispworks' SYS:OPEN-pipe which intends to be a wrapper around popen
creates a bidirectional stream even on linux.

| It seems quite useful for certain trivial cases where you don't have
| to worry about deadlock. For instance, suppose that some program
| accepts a small query command on standard input before producing
| output. If the process reads its input its entirety before trying to
| produce output, or else if the input query fits into the pipe, then
| there is no risk of deadlock.

[I had an anecdote where the Xorg server on linux "deadlocks", merely by
redirecting it's output to a unidirectional pipe: say /dev/xconsole.
The X process blocks because the output end of the pipe has no reader
(yet) and the program to read and display /dev/xconsole never gets a
chance to read the pipe. This requires remote intervention, or on buggy
servers where X crashes the system, a powercycle or reboot. But I think
even programs that are normally designed do non-blocking networked IO,
can block if a standard stream fd is connected to a pipe, and can
eventually deadlock... I think the conceptual benefits of avoiding
deadlock by using unidirectional pipes may be chimeral]

Then there was this famous internet quote:

"If POSIX threads are a good thing, perhaps I donâ??t want to know
what theyâ??re better than." -- Rob Pike.

But I was able to understand the full meaning of that quote only after
trying to use the pipe-stream/socket-stream mechanism from within
Lispworks. The goal was just to run a command as a child process and
interact with its stream, but to do this correctly with "native
threads", this required multiprocessing thread locks around access to
the "spawned unix process". [Unless I'm missing something,
gentlemen. the circle is now complete, and squared!]---Madhu