Discussion:
Trouble trying to use some modules from the docs (Matt Wette)
Mark H Weaver
2018-06-05 19:36:41 UTC
Permalink
Hi,
Something must be up with either the Guile REPL or the Guile REPL inside
Emacs' M-x shell. I tried to run socket in it and it could not find
that. I also ran other code before that, so maybe the issue was, that
that somehow prevented the REPL from finding the bindings. However, now
that I tried what you wrote in a completely new REPL in a XFCE terminal,
it works flawlessly. And such a thing has happened to me before with
another module inside Emacs M-x shell mode.
Can you please post a transcript demonstrating the problem that you're
seeing while trying to run 'socket' in Emacs shell mode, starting from
the beginning of the REPL session?

In general, it's much more useful to show us the precise commands you
typed, and the precise error message, than to write "I tried to run
socket in it and it could not find that". I'd like to understand what's
going on here. I use the Guile REPL from within Emacs all the time, and
it's far more convenient to use from within Emacs than within a bare
terminal. It would be good to get to the bottom of this.

Regards,
Mark
Zelphir Kaltstahl
2018-06-16 09:35:38 UTC
Permalink
Hello,

I have managed to get another case of a binding not being available
according to the Guile REPL, this time I have the code and way to
reproduce the issue.

After some struggling, trying and reading the docs of networking
procedures multiple times, I managed to write a little TCP server and
client example program.
(More examples in this area would be cool and if my code is worth
anything, feel free to take it, improve it, and make an example for TCP
server/client in the docs. Or maybe I can put examples in the docs?)

The directory structure looks as follows (tree):


.
├── main.scm
├── networking-lib
│   └── helpers.scm
├── tcp-client.scm
└── tcp-server.scm


The contents of the files are:


;; ===== HELPERS MODULE (networking-lib/helpers.scm) =====
(use-modules (rnrs bytevectors))

(define-module (networking-lib helpers)
  #:export (display-byte-vector))

(define (display-byte-vector vec len)
  (let ([minimal-vec (make-bytevector len)])
        (bytevector-copy! vec 0 minimal-vec 0 len)
        (display (simple-format #f
                                "I got the following message: ~s\n"
                                (utf8->string minimal-vec)))))
;; ===== HELPERS MODULE END =====



;; ===== CLIENT (tcp-client.scm) =====
(add-to-load-path
 (string-append "/home/xiaolong"
                "/development/Guile"
                "/examples-and-convenience-procedures/network-programming"))
(use-modules (rnrs bytevectors)
             (networking-lib helpers))

(define receive-buffer (make-bytevector 1024))

(define (connect-to-server)
  (let ([sock
         (socket PF_INET SOCK_STREAM
                 (protoent:proto (getprotobyname "TCP")))])
    (connect sock
             (make-socket-address AF_INET
                                  INADDR_LOOPBACK
                                  12345))
    sock))

(define (send-message-to-server sock message)
  (display (simple-format #f "sending message to server: ~s" message))
  (send sock (string->utf8 message)))

(define (receive-message-from-server! sock receive-buffer)
  (recv! sock receive-buffer))

(define in-out-sock (connect-to-server))

(let ([bytes-count (receive-message-from-server! in-out-sock
receive-buffer)])
  (display-byte-vector receive-buffer bytes-count)
  (send-message-to-server in-out-sock "Hello from client!\n"))
;; ===== CLIENT END =====



;; ===== SERVER (tcp-server.scm) =====
(add-to-load-path
 (string-append "/home/user"
                "/development/Guile"
                "/examples-and-convenience-procedures/network-programming"))
(use-modules (rnrs bytevectors)
             (networking-lib helpers)
             (ice-9 threads))

(define receive-buffer (make-bytevector 1024))

(define (create-server-socket)
  (let ([sock
         (socket PF_INET SOCK_STREAM (protoent:proto (getprotobyname
"TCP")))]
        [backlog-of-connection-requests 10])
    (bind sock (make-socket-address AF_INET INADDR_ANY 12345))
    (listen sock backlog-of-connection-requests)
    sock))

(define (send-message-to-client sock message)
  (display (simple-format #f "sending message to client: ~s\n" message))
  (send sock (string->utf8 message)))

(define (handle-messages sock)
  (call-with-new-thread
   (λ ()
     (while #t
       (let* ([client-connection
               (accept sock)]
              [client-details (cdr client-connection)]
              [in-out-sock (car client-connection)])
         (display
          (simple-format #f
                         "Got new client connection: ~S\n"
                         client-details))
         (display
          (simple-format #f
                         "Client address: ~S\n"
                         (gethostbyaddr (sockaddr:addr client-details))))

         (send-message-to-client in-out-sock "Hello from server!\n")
         (display-byte-vector receive-buffer (recv! in-out-sock
receive-buffer))
         (display "closing input-output-socket with client ...\n"))))))

(define sock (create-server-socket))

(handle-messages sock)
;; ===== SERVER END =====



With that code, I do the following:

1. Start two Guile REPLs inside the
.../examples-and-convenience-procedures/network-programming directory.
(in XFCE4 terminal)
2. In the first REPL I paste all code of the server. It starts a new
thread and runs fine without showing any error.
3. In the second REPL I paste all code of the client. It seems to run
fine until I hit the last let form.

The error I get is:


;; ===== ERROR =====
scheme@(guile-user)> (let ([bytes-count (receive-message-from-server!
in-out-sock receive-buffer)])
...   (display-byte-vector receive-buffer bytes-count)
...   (send-message-to-server in-out-sock "Hello from client!\n"))
networking-lib/helpers.scm:7:0: In procedure display-byte-vector:
In procedure module-lookup: Unbound variable: make-bytevector

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>
;; ===== ERROR END =====


But I did import bytevectors in helpers.scm! How can it not find that?
When I paste the procedure defined in helpers.scm into the server and
client programs and do not use the helpers module, it seem to work just
fine.

Is it impossible to use modules inside the helpers module, which are
already used code, which uses the helper module (rnrs bytevectors)?

Regards,
Zelphir
Matt Wette
2018-06-16 13:36:46 UTC
Permalink
Post by Zelphir Kaltstahl
Hello,
I have managed to get another case of a binding not being available
according to the Guile REPL, this time I have the code and way to
reproduce the issue.
;; ===== HELPERS MODULE (networking-lib/helpers.scm) =====
(use-modules (rnrs bytevectors))
(define-module (networking-lib helpers)
  #:export (display-byte-vector))
With above code, bytevector import is NOT in the context of your
module.  Try

(define-module (networking-lib helpers)
  #:export (display-byte-vector))

(use-modules (rnrs bytevectors))


OR


(define-module (networking-lib helpers)
  #:export (display-byte-vector)
  #:use-module (rnrs bytevectors))

Loading...