首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在IPv6专用网络上使用Clozure CL?

如何在IPv6专用网络上使用Clozure CL?
EN

Stack Overflow用户
提问于 2017-09-05 02:03:08
回答 2查看 200关注 0票数 3

当我在IPv6 only网络中工作时,我曾尝试用Clozure CL替换SBCL,但遇到了这样的错误:

代码语言:javascript
复制
MIGRATIONS> (ignore-errors (ccl:make-socket :remote-host "ya.ru" :remote-port 443))
NIL
#<CCL:NO-APPLICABLE-METHOD-EXISTS #x302005215E5D>
MIGRATIONS> (ignore-errors (ccl:make-socket :remote-host "ya.ru" :remote-port 443 :address-family :internet))
NIL
#<CCL:NO-APPLICABLE-METHOD-EXISTS #x3020052549AD>
MIGRATIONS> (ignore-errors (ccl:make-socket :remote-host "ya.ru" :remote-port 443 :address-family :internet6))
#<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/16) #x3020051D4A9D>

问题是,许多库在使用CCL:MAKE-TCP-SOCKET时没有指定address-family或指定:internet

有没有办法在运行时修补ccl:make-socket以覆盖此设置?

EN

回答 2

Stack Overflow用户

发布于 2017-09-09 01:59:22

通知函数

Common Lisp的几个实现允许正常函数的通知(->修补)。建议是一个非标准功能,不同的实现提供它的方式略有不同。CLOS泛型函数的相关机制是标准化的,使用了:before、:after和:after方法。

其目的是在定义函数后向其添加一个或多个补丁,而不更改原始源代码。

通常,这要求对此函数的函数调用不是内联的。

Clozure Common Lisp中的宏建议

可以使用宏ADVISE来完成Clozure CL中的修补函数。请参阅advising的文档。

假设我们有一个函数FOOBAR

代码语言:javascript
复制
? (defun foobar (a b &key c (d :foobar)) (list a b c d))
FOOBAR

TEST内部调用FOOBAR

代码语言:javascript
复制
? (defun test (a) (foobar a 20 :c 30))
TEST

? (test 10)
(10 20 30 :FOOBAR)

我们现在希望修补FOOBAR,以便使用不同的值调用命名为arg的:D

我们更改arglist以在两个必需的参数之后插入新的命名参数:

代码语言:javascript
复制
? (advise foobar (let ((arglist (list* (first arglist)
                                       (second arglist)
                                       :d :ipv6
                                       (cddr arglist))))
                   (:do-it))   ; calling the original function
          :when :around     ; advise around it
          :name :ipv6)      ; the name of this advise
#<Compiled-function (CCL::ADVISED 'FOOBAR) (Non-Global)  #x3020010D1CCF>

现在我们可以调用我们的TEST函数,它将调用建议的函数FOOBAR

代码语言:javascript
复制
? (test 10)
(10 20 30 :IPV6)

CCL的建议:MAKE-SOCKET

您可以为CCL:MAKE-SOCKET编写类似的建议。

未经测试:

代码语言:javascript
复制
(advise ccl:make-socket (let ((arglist (list* :address-family
                                              :internet6
                                              arglist)))
                          (:do-it))
        :when :around
        :name :internet6)
票数 5
EN

Stack Overflow用户

发布于 2017-09-08 03:59:11

这是可以做到的!

首先复制原始的make-socket

代码语言:javascript
复制
(IN-PACKAGE :ccl)
(DEFPARAMETER original-make-socket #'make-socket)

然后重新定义make-socket。注意:您必须提供所有关键字参数的完整规范。实际上,我只使用了您问题中的那些用于演示。

代码语言:javascript
复制
(defun make-socket (&key (remote-host "defau.lt") 
                         (remote-port 443) 
                         (address-family :internet6))
  (declare (ignore address-family))
  (format t "Calling new make-socket with address-family as internet6!")
  (funcall original-make-socket 
           :remote-host remote-host 
           :remote-port remote-port 
           :address-family :internet6))

这将发出continuable error的信号。

在repl处键入:go以继续。这将成功修补make-socket。

现在对make-socket的任何调用都将是对新定义的调用。尝试:

代码语言:javascript
复制
(IN-PACKAGE :cl-user)
(ccl:make-socket :remote-host "ya.ru" :remote-port 443 :address-family :IRRELEVANT)

另一种方法是在重新定义make-socket之前覆盖全局变量*warn-if-redefine-kernel*

代码语言:javascript
复制
(setf *warn-if-redefine-kernel* nil)

这将避免连续误差信号,并直接修补内核函数。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46042158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档