guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Future of g-wrap (and guile wrappers in general).


From: Rob Browning
Subject: Re: Future of g-wrap (and guile wrappers in general).
Date: Tue, 25 Sep 2001 13:22:01 -0500
User-agent: Gnus/5.090004 (Oort Gnus v0.04) Emacs/20.7

Matthias Koeppe <address@hidden> writes:

>> If not, then we'd definitely need a workaround or need to stick with
>> g-wrap for now.
>
> I think you got this wrong.  I gave this example:
>
>         %inline %{
>            double *foo(int *p) { return (double*) p; }
>         %}
>
> The resulting Scheme procedure `foo' would only accept "int *" pointer
> objects and always return "double *" pointer objects.  

Right, but that's not dynamic.  You have to define a function for
every conversion you want in advance.  In g-wrap, you just have to
know the name of the type you want to coerce to, and pass the relevant
object representing the type to the coercion function, along with the
instance you want converted.  This conversion is not smart, and it's
not supposed to be.  It's the equivalent of x = (foo *) y.

And since SWIG's solution isn't dynamic, you can't write scheme side
functions like (glist-map some-func some-glist some-type), i.e.

  (glist-map
    (lambda (gtk-window-ptr)
      ...)
    glist-of-windows
    <GtkWindow*>)

glist-map can be defined to work for all types using gw:wcp-coerce.

> Yes, this is indeed the biggest limitation of current SWIG.  There are
> two passes ("ignore" or "in", then "check"), in which the arguments
> are handled from left to right, where typemaps can emit code to the
> wrapper.  This may not be enough for complicated argument conversions
> spanning multiple arguments.  It would be trivial to add extra passes,
> but I still need to make up my mind on these issues.
>
> How do you tell g-wrap where to put the code pieces?

You give it "ccodegen" and "scmcodegen" lambdas for various purposes,
and each one takes some arguments that are specific to its role, and
is expected to produce a string tree of C or scheme code that should
be inserted into the output.  So, for example, the arg-test-ccodegen
signature looks like this:

  (lambda (arg-info client-only?)
    ;; put code here that uses arg-info to return C code that will
    ;; check the arg's type.  client-only? lets you know whether or
    ;; the code for this particular argument check is going into
    ;; another g-wrapped module that uses this module, or into the
    ;; module implementing this type itself.

    ...)

For example, here's the implementation of the range checked <gw:int>
type.  Note that the init-ccodegen is used to set up the values that
will be used in later range checks (for efficiency), and there's a
global-ccodegen that lets you place definitions, etc.  Oh, and I
freely admit that the current syntax for things is hard to read,
especially without a font-locked buffer, but if/when we can figure out
something as flexible, and more elegant, we'll try and fix it.

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; int
  (let ((wt (gw:wrap-type m '<gw:int> "int" "const int")))

    (gw:type-set-init-ccodegen!
     wt
     (lambda (type client-only?)
       (list
        "gw__module_gw_runtime_scm_intmin = gh_long2scm(INT_MIN);\n"
        "scm_protect_object(gw__module_gw_runtime_scm_intmin);\n"
        "gw__module_gw_runtime_scm_intmax = gh_long2scm(INT_MAX);\n"
        "scm_protect_object(gw__module_gw_runtime_scm_intmax);\n"))) 

    (gw:type-set-global-ccodegen!
     wt
     (lambda (type client-only?)
       (list 
        "static SCM gw__module_gw_runtime_scm_intmin;\n"
        "static SCM gw__module_gw_runtime_scm_intmax;\n")))
    
    (gw:type-set-scm-arg-type-test-ccodegen!
     wt
     (lambda (param)
       ;; I don't know if it's more efficient to work on the C side or
       ;; the scheme side...
       (let ((x (gw:param-get-scm-name param)))
         (list "((scm_integer_p(" x ") == SCM_BOOL_T) &&"
               " (scm_geq_p(" x ", gw__module_gw_runtime_scm_intmin) == 
SCM_BOOL_T) &&"
               " (scm_leq_p(" x ", gw__module_gw_runtime_scm_intmax) == 
SCM_BOOL_T))"))))
    
    (gw:type-set-pre-call-arg-ccodegen!
     wt
     (lambda (param)
       (let* ((scm-name (gw:param-get-scm-name param))
              (c-name (gw:param-get-c-name param)))
         (list c-name "= gh_scm2long(" scm-name ");\n"))))
    
    (gw:type-set-call-ccodegen! wt standard-c-call-gen)
    
    (add-standard-result-handlers!
     wt
     (lambda (scm-name c-name)
       (list scm-name " = gh_long2scm(" c-name ");\n"))))


> Last time I checked, Guile did not seem to be 64-bit capable anyway,
> so I didn't care about the "official" types, especially as they seemed
> to keep changing (scm_t_bits, scm_bits_t, scm_ubits_t etc. IIRC).

It is now :> I just committed patches to CVS that allow "make check"
to succeed on the alpha with only two UNRESOLVED gc tests, and no
failures.

> SWIG tries to provide an ANSI C preprocessor.  It is not identical
> to gcc's preprocessor, but I think that it is a bad idea to rely on
> gcc-isms rather than standardized behaviour, anyway.

But the problem is that if you're going to be compiling your app using
gcc, and especially if you're wrapping headers that are going to be
compiled with gcc, you can't control whether or not those headers, or
other headers they might include rely on gcc-isms, and so you're in
danger of skew between the definitions used by SWIG to generate the
wrappers and the ones actually seen by gcc at compile time.  This
makes me very nervous, especially since these days most larger gui
apps are probably including, indirectly, hundreds or thousands of
headers.

-- 
Rob Browning
rlb @defaultvalue.org, @linuxdevel.com, and @debian.org
Previously @cs.utexas.edu
GPG=1C58 8B2C FB5E 3F64 EA5C  64AE 78FE E5FE F0CB A0AD



reply via email to

[Prev in Thread] Current Thread [Next in Thread]