[Ecls-list] How to wrap C++ classes using ECLs foreign function interface?

Dietrich Bollmann dietrich at formgames.org
Wed Jul 17 12:43:00 UTC 2013


Hi Matt,

On Fri, Jul 12, 2013 at 12:24 AM, Matthew Mondor <mm_lists at pulsar-zone.net>
 wrote:
>
> Perhaps a few reminders, if performance is an issue (it might not
> matter, depending, and are not only addressed to you, but may also
> serve in the mail archive under this thread):
>

Thank you very much for your answer:  performance actually is very
important in my case and I am most grateful for your comments!

- Functions might be faster than methods


Something like this?:

=== definitions ===

(defun make-cube (&key (size 1.0))
  (ffi:c-inline (size) (:double) :pointer-void "new Cube(#0)" :one-liner t))

(defun cube-get-size (cube)
  (ffi:c-inline (cube) (:pointer-void) :double "((Cube*) #0)->getSize()"
:one-liner t))

(defun cube-set-size (cube size)
  (ffi:c-inline (cube size) (:pointer-void :double) :void "((Cube*) #0)->
setSize(#1)" :one-liner t))

(defun cube-delete (cube)
  (ffi:c-inline (cube) (:pointer-void) :void "delete ((Cube*) #0)"
:one-liner t))

=== tests ===

;;; A fist cube:
(setf cube (make-cube))
(format t "instance: ~a~%" cube)
(format t "size: ~a~%" (cube-get-size cube))
(cube-set-size cube 2)
(format t "new size: ~a~%" (cube-get-size cube))
(cube-delete cube)

;;; Experimenting with a second cube instance:
(setf cube (make-cube :size 3))
(format t "size: ~a~%" (cube-get-size cube))
(cube-delete cube)

=== protocoll ===

instance: #<foreign VOID>
size: 1.0d0
new size: 2.0d0
size: 3.0d0

===

If this is significantly faster I will wrap the Rhino C++ API using this
style rather than CLOS wrappers!


> (although there also is the concept of sealed classes, which could also
> help)
>

This sounds interesting!  Does this mean that the methods can be dispatched
statically during compilation?  And is this approach as fast as functional
wrappers would be, but allows to still use something like 'get-size' for
different classes rather than encoding the class in the name of the
function itself (for example by using a prefix like 'cube-' resulting in
'cube-get-size' as in the given example)?

Is something like this implemented for ECL?  If so I would prefer this
approach as encoding the "class" in the name of the wrapper functions makes
the code unnecessarily verbose.


> - MAKE-CUBE (or a variant) could potentially instanciate the object
>   without adding an implicit finalizer, with a corresponding WITH-CUBE
>   or WITH-OBJECT macro responsible for finalization in UNWIND-PROTECT.
>   If I remember the implicit finalization system may be slower
>   (probably a good idea to test instead of trusting my word on this).
>   WITH-* style macros are also a very common lispy interface, require
>   very few indentation and permit explicit, immediate finalization as
>   an option.
>

Like this?:

(unwind-protect
    (let ((cube (make-cube :size 10)))
      (format t "size: ~a~%" (cube-get-size cube))
      (cube-set-size cube 20)
      (format t "new size: ~a~%" (cube-get-size cube)))
  (cube-delete cube))

Or, after defining the macro

(defmacro with-cube ((var &rest args) &body body)
  `(let ((,var (make-cube , at args)))
     (unwind-protect
 (progn , at body)
       (cube-delete ,var))))

like this?:

(with-cube (cube :size 100)
  (format t "size: ~a~%" (cube-get-size cube))
  (cube-set-size cube 200)
  (format t "new size: ~a~%" (cube-get-size cube)))

In my case, I actually found out that Rhino doesn't like me to finalize any
objects anyway and wants to manage them itself:  A lisp variable might get
out of scope but still exist in the Rhino scene.  If I add a finalizer it
forces the destruction of the Rhino object as well - causing Rhino to
crash...


> - Alternatively, instead of full finalization+delete/free in WITH-*/GC,
>   objects could potentially be finalized then cached as slab
>   allocators do; this will help if objects are complex and part of the
>   instanciation+initialization can be preserved.
>

Thank you for this as well.  I wonder if Rhino internally uses a similar
strategy - anyway, in my case I have no other choice than relying on
Rhino's internal management.

Thank you very much for your comments!

If you have some more comments or some information about the concept of
sealed classes, I would be most grateful!

Thanks again,
Dietrich


> --
> Matt
>


On Fri, Jul 12, 2013 at 12:24 AM, Matthew Mondor
<mm_lists at pulsar-zone.net>wrote:

> On Thu, 11 Jul 2013 20:46:15 +0900
> Dietrich Bollmann <dietrich at formgames.org> wrote:
>
> > [An answer to my own posting - I hope this is helpful for others with
> > similar problems]
> >
> > Hi,
> >
> > Here how I finally solved the problem and wrapped the C++ class (sorry
> for
> > the long delay):
> > [...]
>
> That is pretty nice and clean, thanks for following-up this thread;
>
> Perhaps a few reminders, if performance is an issue (it might not
> matter, depending, and are not only addressed to you, but may also
> serve in the mail archive under this thread):
>
> - Functions might be faster than methods (although there also is the
>   concept of sealed classes, which could also help)
>
> - MAKE-CUBE (or a variant) could potentially instanciate the object
>   without adding an implicit finalizer, with a corresponding WITH-CUBE
>   or WITH-OBJECT macro responsible for finalization in UNWIND-PROTECT.
>   If I remember the implicit finalization system may be slower
>   (probably a good idea to test instead of trusting my word on this).
>   WITH-* style macros are also a very common lispy interface, require
>   very few indentation and permit explicit, immediate finalization as
>   an option.
>
> - Alternatively, instead of full finalization+delete/free in WITH-*/GC,
>   objects could potentially be finalized then cached as slab
>   allocators do; this will help if objects are complex and part of the
>   instanciation+initialization can be preserved.
> --
> Matt
>
>
> ------------------------------------------------------------------------------
> See everything from the browser to the database with AppDynamics
> Get end-to-end visibility with application monitoring from AppDynamics
> Isolate bottlenecks and diagnose root cause in seconds.
> Start your free trial of AppDynamics Pro today!
> http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
> _______________________________________________
> Ecls-list mailing list
> Ecls-list at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/ecls-list
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/ecl-devel/attachments/20130717/6c225650/attachment.html>


More information about the ecl-devel mailing list