From eweitz at common-lisp.net Fri Jan 13 07:06:35 2006 From: eweitz at common-lisp.net (Edi Weitz) Date: Fri, 13 Jan 2006 08:06:35 +0100 (CET) Subject: [rdnzl-cvs] CVS update: RDNZL/CHANGELOG.txt RDNZL/ffi.lisp RDNZL/rdnzl.asd Message-ID: <20060113070635.EA60E885A1@common-lisp.net> Update of /project/rdnzl/cvsroot/RDNZL In directory common-lisp.net:/tmp/cvs-serv26247 Modified Files: CHANGELOG.txt ffi.lisp rdnzl.asd Log Message: delegate fixes (Dominic Robinson), version 0.8.0 Date: Fri Jan 13 08:06:29 2006 Author: eweitz Index: RDNZL/CHANGELOG.txt diff -u RDNZL/CHANGELOG.txt:1.3 RDNZL/CHANGELOG.txt:1.4 --- RDNZL/CHANGELOG.txt:1.3 Mon Nov 21 15:03:40 2005 +++ RDNZL/CHANGELOG.txt Fri Jan 13 08:06:28 2006 @@ -1,3 +1,8 @@ +Version 0.8.0 +2006-01-13 +Fix mechanism which releases delegate adapters (thanks to Dominic Robinson) +Updated to DLL version 0.5.0 + Version 0.7.1 2005-11-21 Updated to DLL version 0.4.1 Index: RDNZL/ffi.lisp diff -u RDNZL/ffi.lisp:1.2 RDNZL/ffi.lisp:1.3 --- RDNZL/ffi.lisp:1.2 Fri Jul 8 20:45:34 2005 +++ RDNZL/ffi.lisp Fri Jan 13 08:06:28 2006 @@ -1,7 +1,7 @@ ;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: RDNZL; Base: 10 -*- -;;; $Header: /project/rdnzl/cvsroot/RDNZL/ffi.lisp,v 1.2 2005/07/08 18:45:34 eweitz Exp $ +;;; $Header: /project/rdnzl/cvsroot/RDNZL/ffi.lisp,v 1.3 2006/01/13 07:06:28 eweitz Exp $ -;;; Copyright (c) 2004-2005, Dr. Edmund Weitz. All rights reserved. +;;; Copyright (c) 2004-2006, Dr. Edmund Weitz. All rights reserved. ;;; Redistribution and use in source and binary forms, with or without ;;; modification, are permitted provided that the following conditions @@ -331,7 +331,7 @@ (funcall (gethash index *callback-hash*) args)) (ffi-define-callable - (ReleaseDelegateAdapter ffi-void-pointer) + (ReleaseDelegateAdapter ffi-void) ((index ffi-integer)) ;; remove entry from hash table if CLR is done with it - (remhash index *callback-hash*)) \ No newline at end of file + (remhash index *callback-hash*)) Index: RDNZL/rdnzl.asd diff -u RDNZL/rdnzl.asd:1.2 RDNZL/rdnzl.asd:1.3 --- RDNZL/rdnzl.asd:1.2 Mon Nov 21 15:04:23 2005 +++ RDNZL/rdnzl.asd Fri Jan 13 08:06:28 2006 @@ -1,5 +1,5 @@ ;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- -;;; $Header: /project/rdnzl/cvsroot/RDNZL/rdnzl.asd,v 1.2 2005/11/21 14:04:23 eweitz Exp $ +;;; $Header: /project/rdnzl/cvsroot/RDNZL/rdnzl.asd,v 1.3 2006/01/13 07:06:28 eweitz Exp $ ;;; Copyright (c) 2004, Dr. Edmund Weitz. All rights reserved. @@ -39,7 +39,7 @@ (defsystem #:rdnzl :serial t - :version "0.7.1" + :version "0.8.0" :components ((:file "packages") (:file "specials") (:file "util") From eweitz at common-lisp.net Fri Jan 13 07:06:39 2006 From: eweitz at common-lisp.net (Edi Weitz) Date: Fri, 13 Jan 2006 08:06:39 +0100 (CET) Subject: [rdnzl-cvs] CVS update: RDNZL/doc/index.html Message-ID: <20060113070639.09E0A885A8@common-lisp.net> Update of /project/rdnzl/cvsroot/RDNZL/doc In directory common-lisp.net:/tmp/cvs-serv26247/doc Modified Files: index.html Log Message: delegate fixes (Dominic Robinson), version 0.8.0 Date: Fri Jan 13 08:06:34 2006 Author: eweitz Index: RDNZL/doc/index.html diff -u RDNZL/doc/index.html:1.3 RDNZL/doc/index.html:1.4 --- RDNZL/doc/index.html:1.3 Mon Nov 21 15:03:43 2005 +++ RDNZL/doc/index.html Fri Jan 13 08:06:34 2006 @@ -104,7 +104,7 @@
  • Saving images and application delivery
    1. shutdown-rdnzl -
    2. shutdown-rdnzl +
    3. init-rdnzl
  • Implementation details and things to watch out for @@ -307,7 +307,7 @@ and evaluate (RUN-APROPOS-FORM). If you want to try this -several times start the function in its own thread. In AllegroCL or LispWorks +several times, start the function in its own thread. In AllegroCL or LispWorks that'd be:
    @@ -373,7 +373,7 @@
     
     

    Download and installation

    RDNZL together with this documentation can be downloaded from -http://weitz.de/files/RDNZL.tar.gz, the current version is 0.7.1. It +http://weitz.de/files/RDNZL.tar.gz, the current version is 0.8.0. It doesn't depend on any other Lisp libraries. The C++ source for the shared library RDNZL.dll can be downloaded separately from http://weitz.de/files/RDNZL_cpp.tar.gz but you don't need this archive @@ -399,7 +399,7 @@ For questions, bug reports, feature requests, improvements, or patches please use the rdnzl-devel -mailing list. If you want to be notified about future releases +mailing list. If you want to be notified about future releases, subscribe to the rdnzl-announce mailing list. These mailing lists and the CVS repository were made available thanks to @@ -416,7 +416,7 @@ The current status for the main Win32 Common Lisp implementations is as follows: All implementation-specific parts of RDNZL are located in files called port-acl.lisp, port-ccl.lisp, port-lw.lisp, and so on. If you want to port RDNZL to -another Lisp it should suffice to just create the corresponding +another Lisp, it should suffice to just create the corresponding port-xx.lisp file for your implementation. @@ -461,9 +461,9 @@ for the first argument of INVOKE, PROPERTY, and FIELD) you can also provide the corresponding "native" Lisp objects as long as they can be converted to .NET objects by the function BOX. On the other hand, if -a RDNZL function returns a .NET object it will be automatically +a RDNZL function returns a .NET object, it will be automatically translated to a Lisp object by UNBOX if possible. If a RDNZL function -call doesn't return a result (i.e. if its return type is System.Void) +call doesn't return a result (i.e. if its return type is System.Void), then the keyword :VOID is returned. If a NULL object is returned, RDNZL returns NIL and T as a second return value because otherwise there'd be no difference from returning a false boolean value. @@ -528,7 +528,7 @@ constructor based on the signature determined by args. type can either be a container representing a .NET type or a string naming the type.

    -If type is a delegate type then there should be exactly one more +If type is a delegate type, then there should be exactly one more argument to NEW and it must be a Lisp closure with a corresponding signature. This is how callbacks from .NET into Lisp are implemented. (See the second example above and look for KeyPressEventHandler.) @@ -560,8 +560,8 @@


    Invokes the public .NET method named by the string method-name. If -object is a container an instance method is invoked. If object is a -string the static method of the type named by this string is invoked. +object is a container, an instance method is invoked. If object is a +string, the static method of the type named by this string is invoked.


    [Accessor] @@ -570,8 +570,8 @@


    Gets or sets the public .NET property named by the string -property-name. If object is a container an instance property is -accessed. If object is a string the static property of the type named +property-name. If object is a container, an instance property is +accessed. If object is a string, the static property of the type named by this string is accessed.
    @@ -581,8 +581,8 @@

    Gets or sets the public .NET field named by the string field-name. If -object is a container an instance field is accessed. If object is a -string the static field of the type named by this string is accessed. +object is a container, an instance field is accessed. If object is a +string, the static field of the type named by this string is accessed.


    [Function] @@ -592,7 +592,7 @@ Makes a pass-by-reference type out of object and returns object. If -object is not a container +object is not a container, it'll be boxed first. This function makes only sense if object is used as an argument to INVOKE! (And after INVOKE has been @@ -707,7 +707,7 @@
    rdnzl-error-exception condition => exception


    -If condition is an error of type RDNZL-ERROR then this function will +If condition is an error of type RDNZL-ERROR, then this function will return the .NET exception object that was actually raised.
    @@ -735,13 +735,13 @@ This is boring and error-prone, so RDNZL provides two ways to make it easier for you: You can import types and you can use namespaces.

    -If you import a type RDNZL internally remembers its assembly-qualified +If you import a type, RDNZL internally remembers its assembly-qualified name and you can now use its full name (like "System.Windows.Forms.Button") instead.

    -If this is still too long for you you can use namespaces to further +If this is still too long for you, you can use namespaces to further abbreviate type names. So, if you are using the namespace -"System.Windows.Forms" you can just call the type "Button". Note that +"System.Windows.Forms", you can just call the type "Button". Note that this'll only work for imported types, though.


    [Function] @@ -751,13 +751,13 @@ Imports the .NET type type, i.e. registers its name as one that can be abbreviated (see USE-NAMESPACE) and creates a mapping from its short name to its assembly-qualified name (if necessary). If type is a -string and assembly is NIL then the function will try to create the +string and assembly is NIL, then the function will try to create the type from the string with the static .NET method System.Type::GetType. If type is a string and assembly is a container representing an -assembly then instead the .NET instance method +assembly, then instead the .NET instance method System.Reflection.Assembly::GetType will be used. If type is already -a .NET object (i.e. a container) then the function will just register -its name. If assembly is a true value then the name will also be +a .NET object (i.e. a container), then the function will just register +its name. If assembly is a true value, then the name will also be mapped to its assembly-qualified name. In all cases the type itself (as a container) will be returned. @@ -778,7 +778,7 @@


    Imports all public types of the assembly assembly (a string or a -container). If assembly is a string then the assembly is first loaded +container). If assembly is a string, then the assembly is first loaded with LOAD-ASSEMBLY. Returns assembly as a container.
    @@ -844,7 +844,7 @@
     (invoke type "IsSubclassOf" other-type)
     
    -If the symbol starts with a percent or dollar sign then it is removed +If the symbol starts with a percent or dollar, sign then it is removed and the result is a call to PROPERTY or FIELD respectively:
    @@ -852,7 +852,7 @@
     [$textBox control]  =>  (field control "textBox")
     
    -If the symbol contains a dot then in all three cases this'll result in +If the symbol contains a dot, then in all three cases this'll result in a static invocation where the part before the (last) dot is used as the name of the type: @@ -862,7 +862,7 @@ [$OpCodes.Switch] => (field "Opcodes" "Switch")
    -If the symbol starts with a plus or minus sign then this sign is replaced +If the symbol starts with a plus or minus sign, then this sign is replaced with "add_" or "remove_" respectively. This is the convention used to add or remove event handlers: @@ -939,10 +939,10 @@
    define-rdnzl-call lisp-name (&key member-kind dotnet-name type-name doc-string) args => lisp-name

    -Defines a Lisp function named by the function name lisp-name which invokes the .NET member named by the string dotnet-name. member-kind must be one of the keywords :METHOD, :PROPERTY, or :FIELD and obviously determines whether a method, a property, or a field is to be invoked - the default is :METHOD. If type-name is NIL (which is the default) an instance member is invoked, otherwise type-name should be a string naming a .NET type and a static member of this type is invoked instead. doc-string, if provided, should be a string, namely the documentation string for the Lisp function which is created. If doc-string is NIL (which is the default) a generic documentation string will be created. +Defines a Lisp function named by the function name lisp-name which invokes the .NET member named by the string dotnet-name. member-kind must be one of the keywords :METHOD, :PROPERTY, or :FIELD and obviously determines whether a method, a property, or a field is to be invoked - the default is :METHOD. If type-name is NIL (which is the default), an instance member is invoked, otherwise type-name should be a string naming a .NET type and a static member of this type is invoked instead. doc-string, if provided, should be a string, namely the documentation string for the Lisp function which is created. If doc-string is NIL (which is the default), a generic documentation string will be created.

    -If dotnet-name is NIL (which is the default) then the name of the .NET member will be created from lisp-name be the following rules: -Take the symbol name of lisp-name and if it does not consist solely of hyphens and single-case letters just return it. Otherwise remove the hyphens and downcase all letters except for the first one and those that follow a hyphen - these are upcased. If lisp-name is a list (SETF symbol) then we use symbol instead of lisp-name. Here are some examples (note that the package doesn't matter): +If dotnet-name is NIL (which is the default), then the name of the .NET member will be created from lisp-name be the following rules: +Take the symbol name of lisp-name and if it does not consist solely of hyphens and single-case letters, just return it. Otherwise remove the hyphens and downcase all letters except for the first one and those that follow a hyphen - these are upcased. If lisp-name is a list (SETF symbol), then we use symbol instead of lisp-name. Here are some examples (note that the package doesn't matter):

    @@ -980,7 +980,7 @@ sure that no references to .NET objects remain in the image and finally call SHUTDOWN-RDNZL prior to saving or delivering.

    -If you restart the image or start the executable make sure to call +If you restart the image or start the executable, make sure to call INIT-RDNZL before accessing any RDNZL functionality. That should do the trick.

    @@ -993,7 +993,7 @@


    Prepares RDNZL for delivery or image saving. After calling this function RDNZL can't be used anymore unless INIT-RDNZL is called -again. If no-gc is NIL (the default) a full garbage collection is +again. If no-gc is NIL (the default), a full garbage collection is also performed.
    @@ -1013,10 +1013,10 @@ the MOP to map .NET types to CLOS classes. I have removed this code in favor of a simpler approach because using the MOP results in a lot of overhead at runtime and doesn't work well with application -delivery. In fact, a lot of design decisions in RDNZL are based on the +delivery. In fact, a lot of the design decisions in RDNZL are based on the fact that I want to be able to easily deliver small executables. If it were just for speed and/or convenience, RDNZL would look differently.

    -If you're concerned about speed keep in mind that calls into .NET are +If you're concerned about speed, keep in mind that calls into .NET are expensive because a lot of marshalling of arguments is happening behind the scenes and the system deploys the .NET reflection API at runtime. It is advisable to keep interaction between .NET and Lisp out @@ -1024,7 +1024,7 @@ fully in .NET.

    If you want to know more about the way methods are -looked up in RDNZL read Pedro Pinto's paper +looked up in RDNZL, read Pedro Pinto's paper about the implementation of Dot-Scheme the basics of which apply to RDNZL as well.

    @@ -1046,10 +1046,21 @@ used. Currently, the only way to avoid these problems with cyclic references is: "So don't do that!"

    +If .NET calls back into Lisp from a "foreign" thread (one that wasn't +created by Lisp), this'll not work in some implementations. +Specifically, as +Dominic Robinson has pointed out, there might be GC issues in this +case. +See here +and here +for possible workarounds for LispWorks. +

    About the name: It was pretty clear to me from the beginning that the name of the library should be "RDNZL." -However, I'm not sure what this acronym exactly stands for. Surely "L" is +However, I'm not sure what this acronym exactly stands for. Surely, "L" is for "Lisp" and "DN" is for "DotNet". The rest? You'll figure it out... :)
     

    Acknowledgements

    @@ -1063,7 +1074,7 @@

    Thanks to Charles A. Cox for the port of RDNZL to AllegroCL. Thanks to Vasilis Margioulas for the CLISP port. Thanks to Roger Corman for his help with the CCL port. Thanks to Franz Inc. (and particularly Jans Aasman) for supporting the development of RDNZL.

    -$Header: /project/rdnzl/cvsroot/RDNZL/doc/index.html,v 1.3 2005/11/21 14:03:43 eweitz Exp $ +$Header: /project/rdnzl/cvsroot/RDNZL/doc/index.html,v 1.4 2006/01/13 07:06:34 eweitz Exp $

    BACK TO MY HOMEPAGE From eweitz at common-lisp.net Fri Jan 13 07:08:46 2006 From: eweitz at common-lisp.net (Edi Weitz) Date: Fri, 13 Jan 2006 08:08:46 +0100 (CET) Subject: [rdnzl-cvs] CVS update: RDNZL-cpp/CHANGELOG.txt Message-ID: <20060113070846.77348885A1@common-lisp.net> Update of /project/rdnzl/cvsroot/RDNZL-cpp In directory common-lisp.net:/tmp/cvs-serv26572 Modified Files: CHANGELOG.txt Log Message: delegate adapter fixes (Dominic Robinson), version 0.5.0 Date: Fri Jan 13 08:08:45 2006 Author: eweitz Index: RDNZL-cpp/CHANGELOG.txt diff -u RDNZL-cpp/CHANGELOG.txt:1.2 RDNZL-cpp/CHANGELOG.txt:1.3 --- RDNZL-cpp/CHANGELOG.txt:1.2 Mon Nov 21 15:05:40 2005 +++ RDNZL-cpp/CHANGELOG.txt Fri Jan 13 08:08:44 2006 @@ -1,3 +1,7 @@ +Version 0.5.0 +2006-01-13 +Fix mechanism which releases delegate adapters (thanks to Dominic Robinson) + Version 0.4.1 2005-11-21 Added missing constructor for single float (caught by Andrew Wolven) From eweitz at common-lisp.net Fri Jan 13 07:08:47 2006 From: eweitz at common-lisp.net (Edi Weitz) Date: Fri, 13 Jan 2006 08:08:47 +0100 (CET) Subject: [rdnzl-cvs] CVS update: RDNZL-cpp/RDNZL/DelegateAdapter.cpp RDNZL-cpp/RDNZL/DelegateAdapter.h Message-ID: <20060113070847.35314885A6@common-lisp.net> Update of /project/rdnzl/cvsroot/RDNZL-cpp/RDNZL In directory common-lisp.net:/tmp/cvs-serv26572/RDNZL Modified Files: DelegateAdapter.cpp DelegateAdapter.h Log Message: delegate adapter fixes (Dominic Robinson), version 0.5.0 Date: Fri Jan 13 08:08:46 2006 Author: eweitz Index: RDNZL-cpp/RDNZL/DelegateAdapter.cpp diff -u RDNZL-cpp/RDNZL/DelegateAdapter.cpp:1.1.1.1 RDNZL-cpp/RDNZL/DelegateAdapter.cpp:1.2 --- RDNZL-cpp/RDNZL/DelegateAdapter.cpp:1.1.1.1 Mon Jan 3 02:00:48 2005 +++ RDNZL-cpp/RDNZL/DelegateAdapter.cpp Fri Jan 13 08:08:46 2006 @@ -1,6 +1,6 @@ -// $Header: /project/rdnzl/cvsroot/RDNZL-cpp/RDNZL/DelegateAdapter.cpp,v 1.1.1.1 2005/01/03 01:00:48 eweitz Exp $ +// $Header: /project/rdnzl/cvsroot/RDNZL-cpp/RDNZL/DelegateAdapter.cpp,v 1.2 2006/01/13 07:08:46 eweitz Exp $ // -// Copyright (c) 2004-2005, Dr. Edmund Weitz. All rights reserved. +// Copyright (c) 2004-2006, Dr. Edmund Weitz. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ #include "DelegateAdapter.h" // the destructor notifies Lisp that this instance is no longer used - -// at least in theory, this doesn't seem to work right now +// might be called from a "foreign" thread, see docs DelegateAdapter::~DelegateAdapter() { release(indexIntoLisp); } @@ -53,7 +53,7 @@ // this static function is called once in the beginning to initialize // the function pointers pointing to two Lisp callbacks -void setFunctionPointers(void *(*callback_fp)(int, void *), void *(*release_fp)(int)) { +void setFunctionPointers(void *(*callback_fp)(int, void *), void (*release_fp)(int)) { DelegateAdapter::callback = callback_fp; DelegateAdapter::release = release_fp; } Index: RDNZL-cpp/RDNZL/DelegateAdapter.h diff -u RDNZL-cpp/RDNZL/DelegateAdapter.h:1.1.1.1 RDNZL-cpp/RDNZL/DelegateAdapter.h:1.2 --- RDNZL-cpp/RDNZL/DelegateAdapter.h:1.1.1.1 Mon Jan 3 02:00:48 2005 +++ RDNZL-cpp/RDNZL/DelegateAdapter.h Fri Jan 13 08:08:46 2006 @@ -1,6 +1,6 @@ -// $Header: /project/rdnzl/cvsroot/RDNZL-cpp/RDNZL/DelegateAdapter.h,v 1.1.1.1 2005/01/03 01:00:48 eweitz Exp $ +// $Header: /project/rdnzl/cvsroot/RDNZL-cpp/RDNZL/DelegateAdapter.h,v 1.2 2006/01/13 07:08:46 eweitz Exp $ // -// Copyright (c) 2004-2005, Dr. Edmund Weitz. All rights reserved. +// Copyright (c) 2004-2006, Dr. Edmund Weitz. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions @@ -36,7 +36,7 @@ void init(int index); Object *invoke (Object* args[]); static void *(*callback)(int, void *); - static void *(*release)(int); + static void (*release)(int); private: // the index into the Lisp hash table which holds the closures - // should be a 64-bit integer in the future @@ -44,5 +44,5 @@ }; extern "C" { - __declspec(dllexport) void setFunctionPointers(void *(*callback_fp)(int, void *), void *(*release_fp)(int)); + __declspec(dllexport) void setFunctionPointers(void *(*callback_fp)(int, void *), void (*release_fp)(int)); }

    lisp-name dotnet-name