Dear Chris,

thank you very much for working on this wrapper! I tried to get your code working on MacOS. I know you only did it for Linux so far, but I am really interested in this stuff :)

I installed libffi in /usr/local, and libffi installed its header files ffi.h and ffitarget.h into /usr/local/lib/libffi-3.0.4/ include/. The compiler did not find them there, but was content after I created symbolic links to these files in /usr/local/include. Also, I had to change

#include <malloc.h>

into

#include <malloc/malloc.h>

After these edits, the compiler errors reduced to the following

$ oztool c++ -c ozffi.cpp -o ozffi.o
ozffi.cpp: In function 'OZ_Return BIcall(OZ_Term**)':
ozffi.cpp:316: error: invalid conversion from 'void (*)()' to 'void (*)(...)' ozffi.cpp:316: error: initializing argument 2 of 'void ffi_call (ffi_cif*, void (*)(...), void*, void**)'


Any idea how to get around this issue?

Thank you very much!

Best
Torsten

On Feb 27, 2008, at 12:40 PM, Chris Double wrote:

I'm playing around with a wrapper for libffi so I can access functions
in shared libraries without writing wrappers in C.

It's very simple at the moment and has only been tested on Linux.
Before I go any further I thought I'd better check and see if there is
already anything like this out there that I should use instead or get
feedback on design, etc. I will get this working on Windows and Mac OS
X and clean it up if it proves useful.

There is a 'ffitest.oz' file which shows very simple example of usage,
and can be tried line by line from the interactive environment. Here's
some simple usage:

First load the module:
  declare [FFI]={Module.link ['ffi.ozf']}

This provides a few procedures. The first, 'load' takes a path or name
for a shared library and loads it. It returns an extension object that
needs to be passed to the other calls. The name of the shared library
can be 'nil' to represent using a name from the shared libraries
loaded by the current process. This is what the following line does:

  declare Std = {FFI.load nil}

The second procedure is 'bind'. This will take the extension object
returned above, the name of a function, and a tuple describing the
functions return types and arguments. It will return a procedure, that
when called, will marshall types, call the C function, and return the
relevant value. e.g:

declare GetEnv = {FFI.bind Std "getenv" stdcall(string getenv (string))}
  {Browse {GetEnv "OZHOME}}

This will show the value of the OZHOME environment variable in the
browser. Hopefully. I haven't decided on the final syntax of the tuple
describing the arguments yet. At the moment it looks like:

  stdcall(<returntype> <ignored>(<argtype1> <argtype2> ...))

stdcall and <ignored> are ignored. Originally I was going to use them
for the calling argument convention and the function name but ended up
not doing this. The types can be any of:

pointer - any C pointer type, from Oz it needs to be a foreignPointer
  string - a C char*, or Oz String
  uint8 - 8 bit unsigned integer from C, Number in Oz
  sint8 - 8 bit signed integer from C, Number in Oz
  uint16 - 16 bit unsigned integer from C, Number in Oz
  sint16 - 16 bit signed integer from C, Number in Oz
  uint32 - 32 bit unsigned integer from C, Number in Oz
  sint32 - 32 bit signed integer from C, Number in Oz
  uint64 - 64 bit unsigned integer from C, Number in Oz
  sint64 - 64 bit signed integer from C, Number in Oz
  float - float in C, float in Oz
  double - double in C, float in Oz

Another example:
declare Pow = {FFI.bind Std "pow" stdcall(double pow(double double))}
  {Browse {Pow 2.0 6.0}}

This should show 64.0 in the browser.

The library has a number of limitations at the moment which I hope to
fix. This first is that there is no support for defining and using C
structures. I need to think of a good way of doing this. There are
memory leaks when calling C functions due to be not correctly cleaning
up copies of atoms, etc. There is a hard coded limit on the number of
arguments. Currently it's 3 but I can make this more. It's hard coded
due to the implementation of Bind which does this:

      NumArgs = {Width Type.2}
   in
      if NumArgs == 0 then
         proc {$ R}
            Fun
         in
            {FFI.bind F Name Fun}
            {FFI.call Fun Type nil R}
         end
      elseif NumArgs == 1 then
         proc {$ A R}
            Fun
         in
            {FFI.bind F Name Fun}
            {FFI.call Fun Type [ A ] R}
         end
      elseif NumArgs == 2 then
         proc {$ A B R}
            Fun
         in
            {FFI.bind F Name Fun}
            {FFI.call Fun Type [ A B ] R}
         end
      elseif NumArgs == 3 then

Is there A way of defining a procedure which can have a variable
number of arguments? I didn't find a way so resorted to this approach.
Any thoughts on a better way?

I'm an Oz/Mozart newbie so comments on the way I'm doing things are
appreciated. My work in progress is available from:

http://www.bluishcoder.co.nz/ozffi.tar.gz
In the archive is a simple build.sh shell script that will build the
native extension and the .oz wrapper. You need to have libffi
installed. In Ubuntu this is done with:

sudo apt-get install libffi4 libffi4-dev

Or you can build from source:

http://sources.redhat.com/libffi/

A git repository holding the source can be retrieved with:

git clone git://double.co.nz/git/ozffi.git

or

git clone http://double.co.nz/git/ozffi.git

A gitweb view is at:
http://www.double.co.nz/cgi-bin/gitweb.cgi?p=ozffi.git;a=summary

Chris.
--
http://www.bluishcoder.co.nz
______________________________________________________________________ ___________ mozart-users mailing list mozart- [EMAIL PROTECTED]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

--
Torsten Anders
Interdisciplinary Centre for Computer Music Research
University of Plymouth
Office: +44-1752-233667
Private: +44-1752-558917
http://strasheela.sourceforge.net
http://www.torsten-anders.de




_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to