[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