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

Dietrich Bollmann dietrich at formgames.org
Thu Jul 11 11:46:15 UTC 2013


[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):

The C++ class:

---
/*
  Cube.h, Dietrich Bollmann, Kamakura 2013/06/15
*/

#ifndef CUBE_H
#define CUBE_H

class Cube {
private:
  double _size;
public:
  Cube();
  Cube(const double size);
  void setSize(const double size);
  double getSize() const;
};

#endif

// fin.
---

and

---
/*
  Cube.cpp, Dietrich Bollmann, Kamakura 2013/06/15
*/

#include "StdAfx.h"
#include "Cube.h"

#include <iostream>

using namespace std;

Cube::Cube(): _size(1.0) {}
Cube::Cube(const double size): _size(size) {}

void Cube::setSize(const double size) { _size = size; }
double Cube::getSize() const { return _size; }

// fin.
---

Here the lisp wrapper:

---
(defclass cube ()
  ((c++-instance
   :initarg :c++-instance
   :reader c++-instance)))

(defun finalize-cube (cube)
  (format t "~&;;; [DEBUG] Deleting C++ Cube instance ~a~%" (c++-instance
cube))
  (ffi:c-inline ((c++-instance cube)) (:pointer-void) :void "delete
((Cube*) #0)" :one-liner t))

(defmethod initialize-instance :before ((cube cube) &rest args)
  (declare (ignore args))
  (ext:set-finalizer cube #'finalize-cube))

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

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

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

Testing the CLOS wrapper for the C++ 'Cube':

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

;;; Deleting the reference to the first cube instance:
(setf cube nil)

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

;;; Deleting the reference to the second cube instance
(setf cube nil)

;;; Waiting 3 seconds
(loop for i from 1 to 3 do (format t ".") (sleep 1) finally (format t "~%"))

;;; Initiating the garbage collector:
(si::gc t)
---

And here the protocol:

---
instance: #<foreign VOID>
size: 1.0d0
new size: 2.0d0
size: 3.0d0
...
;;; [DEBUG] Deleting C++ Cube instance #<foreign VOID>
;;; [DEBUG] Deleting C++ Cube instance #<foreign VOID>
---

I hope this is helpful, all the best,

Dietrich



On Tue, Jun 11, 2013 at 12:05 PM, Juan Jose Garcia-Ripoll <
juanjose.garciaripoll at gmail.com> wrote:

>
> On Mon, Jun 10, 2013 at 7:57 PM, Dietrich Bollmann <dietrich at formgames.org
> > wrote:
>
>> So concerning the simple C++ example I gave before in this thread, which
>> FFI version do you advice me to use? Which one is easier to use for
>> wrapping a whole C++ API?
>>
>
> ECL's with embedded C++ code.
>
>
>> Which one would result in the faster code?
>>
>
> Definitely embedding C++ code because the CFFI/UFFI wrappers are not
> always optimal.
>
> Blender 3D generates their Python API mostly automatically from the C and
>> C++ sources.  Is something like this thinkable with ECL?
>>
>
> I do not know how Blender does it. Even the most sophisticated approach
> discussed here in the mailing list and based on Boost's template library
> for Python demands hand-writing the wrapper declarations.
>
> Juanjo
>
>
> --
> Instituto de Física Fundamental, CSIC
> c/ Serrano, 113b, Madrid 28006 (Spain)
> http://juanjose.garciaripoll.googlepages.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/ecl-devel/attachments/20130711/88e8fdad/attachment.html>


More information about the ecl-devel mailing list