I read sbcl manual,and have a problem at the 8.5 Foreign Data Structure Examples chapter.
I use following examples to verify whether it can run correct.
_______________________________________________________________
Or consider this example of an external C variable and some accesses:
struct c_struct {
short x, y;
char a, b;
int z;
c_struct *n;
};
extern struct c_struct *my_struct;
my_struct->x++;
my_struct->a = 5;
my_struct = my_struct->n;
which can be manipulated in Lisp like this:
(define-alien-type nil
(struct c-struct
(x short)
(y short)
(a char)
(b char)
(z int)
(n (* c-struct))))
(define-alien-variable "my_struct" (* c-struct))
(incf (slot my-struct 'x))
(setf (slot my-struct 'a) 5)
(setq my-struct (slot my-struct 'n))
________________________________________________________________
Now I run above example code on slime,and it signaled a error.
unknown alien type: C-STRUCT
[Condition of type SIMPLE-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [ABORT] Return to sldb level 7.
2: [RETRY] Retry SLIME REPL evaluation request.
3: [ABORT] Return to sldb level 6.
4: [RETRY] Retry SLIME REPL evaluation request.
5: [ABORT] Return to sldb level 5.***
What should I do to define such a struct that can contain it's self point.
Note that the manual also says:
Types may be either named or anonymous. With structure and union types, the name is part of the type specifier, allowing recursively defined types such as:
(struct foo (a (* (struct foo))))
I haven't used SBCL's FFI, but I'd guess that means that you should use:
(define-alien-variable "my_struct" (* (struct c-struct)))
Related
Emacs version: 26.3
Slime version: 2.26.1
I start up Emacs.
I open up a simple .lisp file.
(defun testfn (x y)
(+ x y))
(defmacro testmc (form)
form
`(list 1 2 3))
I place my cursor over the symbol defun and issue the keyboard-command M-. (slime-edit-definition).
This should bring me to the definition of defun.
But it doesn't.
It brings me here:
I place my cursor over the symbol defmacro and issue the keyboard-command M-. (slime-edit-definition).
This should bring me to the definition of defmacro.
But it doesn't.
It brings me here:
Why does it do this & how do I fix this
Notice there is a warning in the REPL when trying to find the source of DEFUN:
WARNING: inconsistent 2 form-number-translations
You can replicate it yourself in the REPL:
CL-USER> (let ((slynk::*buffer-package* (find-package :cl))
(slynk::*buffer-readtable* *readtable*))
(slynk:find-definitions-for-emacs "DEFUN"))
WARNING: inconsistent 2 form-number-translations
(("(DEFMACRO DEFUN)"
(:LOCATION (:FILE "/home/chris/data/src/sbcl/src/code/macros.lisp")
(:POSITION 4140)
(:SNIPPET "(setq doc nil)
(let* (;; stuff shared between LAMBDA and INLINE-LAMBDA and NAMED-LAMBDA
(lambda-guts `(,#decls (block ,(fun-name-block-name name) ,#forms)))
(lambda `(lambda ,lambda-list ,#lambda-guts))
(named-lambda `("))))
To find where the warning comes from, you could do as I did first and do a textual search on the repository, or you could use the following alternate method that works better, namely invoke the debugger on warnings:
(handler-bind ((warning (lambda (c) (invoke-debugger c))))
(let ((slynk::*buffer-package* (find-package :cl))
(slynk::*buffer-readtable* *readtable*))
(slynk:find-definitions-for-emacs "DEFUN")))
This comes from SLYNK-SBCL::FORM-NUMBER-POSITION, and the interesting value in the debugger is the source location obtained from SBCL:
#<SB-INTROSPECT:DEFINITION-SOURCE {10369C50F3}>
--------------------
The object is a STRUCTURE-OBJECT of type SB-INTROSPECT:DEFINITION-SOURCE.
PATHNAME: #P"SYS:SRC;CODE;MACROS.LISP"
FORM-PATH: (5)
FORM-NUMBER: 89
CHARACTER-OFFSET: 3917
FILE-WRITE-DATE: 3825178034
PLIST: NIL
DESCRIPTION: NIL
It says the source is the fifth toplevel form in the file (which corresponds to the character offset), and from here, the FORM-NUMBER is the 89th form in a depth-first search walk of the form (this comes from the structure's docstring).
But, if I recompile the function FORM-NUMBER-POSITION with DEBUG set to 3, the toplevel form read at this position, TLF is NIL:
1: (SLYNK-SBCL::FORM-NUMBER-POSITION #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL..
Locals:
DEFINITION-SOURCE = #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL :DESCRIPTION NIL)
FORM-NUMBER = 89
PATH-TABLE = #((0 0))
POS-MAP = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
POS-MAP#1 = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
STREAM = #<SB-IMPL::STRING-INPUT-STREAM {7F3E0350D953}>
TLF = NIL
TLF#1 = NIL
TLF-NUMBER = 5
In read-source-form, you can see that the form is being read inside a (ignore-errors (read ...)) form, which returns NIL in case of error. I tried calling (read ...) only but this somehow did not invoke the debugger, so I did the same thing as above and explicitly invoked it on any condition.
There is an error, namely that the package "SB-XC" does not exist, which is expected since, if I am not mistaken, this is a package that only exists during the compilation of SBCL itself.
I think you should contact the SBCL SLY developers and file a bug for this directly, they would certainly have a better idea of how to fix the behaviour (feel free to link to your question in addition to giving the usual details of the bug report).
I'm seeing pretty much what you're seeing.
Defun (line 280 of defboot.lisp) is a macro, which is defined in terms of defun-expander (line 230 of defboot.lisp) which is what you're seeing.
Whereas, defmacro takes you directly to its definition (line 15 of defmacro.lisp) which is what you're seeing.
It seems to be doing useful things.
I defined a new function 'addmore'
(defun addmore (x y z)
(testfn x (testfn y z)))
I compiled it all, and M-. on 'addmore' takes me to the definition of testfn.
So I think it's all working.
Suppose I have this struct:
(struct pos (x y))
I can create instances of this struct using:
(pos 1 2)
Suppose I want to use keyword arguments instead. For example:
(pos #:x 1 #:y 2)
This results in an error:
> (pos #:x 1 #:y 2)
; application: procedure does not accept keyword arguments
; procedure: pos
; [,bt for context]
How can I use keyword arguments when creating instances of structs?
You can't do that with native struct, so you either have to roll your own constructor as #tfb suggests, or use third-party libraries that provide this feature.
https://docs.racket-lang.org/struct-plus-plus/
https://docs.racket-lang.org/rebellion/Record_Types.html
Lets say I have a generator for interval structs e.g.
(struct interval (lo hi)
#:methods gen:custom-write
[(define write-proc
(make-constructor-style-printer
(lambda (obj) 'interval)
(lambda (obj) (list (interval-hi obj) (interval-lo obj)))))])
(define (choose-interval [min-value -100] [max-value 100])
(bind-generators
([lo (choose-real min-value max-value)]
[hi (choose-real lo max-value)])
(interval lo hi)))
According to the docs generator has a member called proc that takes a test size argument and a random number generator. But where do I get this random number generator? The make-random-generator symbol in the docs is not actually exported by the module!
How do i get some values out of this generator so I can be sure it is working correctly?
make-random-generator should be exported. See This PR.
I want to create a lisp function which corresponds to a macro in C.
e.g., there is one HIWORD in win32 API, which is defined as a macro in the header file.
I tried to define it as below but was told that HIWORD is unresolved.
CL-USER 4 > (hiword #xFFFFFFFF)
Error: Foreign function HIWORD trying to call to unresolved external function "HIWORDW".
I just want to know how to create a wrapper for C macros like for C functions.
(fli:define-c-typedef DWORD (:unsigned :long))
(fli:define-c-typedef WORD (:unsigned :short))
(fli:define-foreign-function
(HIWORD "HIWORD" :dbcs)
((dwVal dword))
:result-type word :calling-convention :stdcall)
You cannot do this directly. C preprocessor macros are not preserved in the compilation process, i.e., there is simply no artifact in the generated object files, which would correspond to the C macro itself (though its expansion may be part of the object file multiple times). And since there is no artifact, there is nothing to bind to with FFI.
You can, however, provide a wrapper function
#define HIGHWORD(x) /* whatever */
int
highword_wrapper(int x)
{
return HIGHWORD(x);
}
and this one can be used with FFI.
No need to jump into another language. Shifting and masking in Lisp:
(defun hiword (val)
(logand (ash val -16) #xFFFF)
(defun loword (val) ;; ditto
(logand val #xFFFF))
Another way: using the ldb accessor with ranges expressed using byte syntax:
(defun hiword (val)
(ldb (byte 16 16) val) ;; get 16-bit-wide "byte" starting at bit 16.
(defun loword (val)
(ldb (byte 16 0) val) ;; get 16-bit-wide "byte" at position 0.
The macro, transform!, as defined below seems to work for => (transform! ["foo" 1 2 3]). The purpose is to take in a list, with the first element being a string that represents a function in the namespace. Then wrapping everything into swap!.
The problem is that transform! doesn't work for => (transform! coll), where (def coll ["foo" 1 2 3]). I am getting this mystery exception:
#<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Symbol>
The function:
(defmacro transform!
" Takes string input and update data with corresponding command function.
"
[[f & args]] ;; note double brackets
`(swap! *image* ~(ns-resolve *ns* (symbol f)) ~#args))
I find it strange that it works for one case and not the other.
Macros work at compile-time and operate on code, not on runtime data. In the case of (transform! coll), the macro is being passed a single, unevaluated argument: the symbol coll.
You don't actually need a macro; a regular function will suffice:
(defn transform! [[f & args]]
(apply swap! *image* (resolve (symbol f)) args)))
Resolving vars at runtime could be considered a code smell, so think about whether you really need to do it.
You're passing a symbol to the macro, namely coll. It will try to pull that symbol apart according to the destructuring statement [f & args], which won't be possible of course.
You can also use (resolve symbol) instead of (ns-resolve *ns* symbol).