Giter Site home page Giter Site logo

r6rs-pffi's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

r6rs-pffi's Issues

Dealing with typedef integers

How would you specify that a foreign procedures uses an integer type like size_t or mode_t whose size can vary by operating system and CPU architecture?

Pass address of double to foreign procedure

Hi,

Thanks for the library!

Could you please suggest how to pass the address of a double to a foreign procedure? For instance, given:

void
set_pi (double *x)
{
  *x = 3.14;
}

I'd like the equivalent of set_pi (&x) in scheme. I guess something like:

(define set-pi! (foreign-procedure lib void set_pi (pointer)))

(let ((x 0.0))
  (set-pi! (... x))
  x)  ; -> 3.14

where I don't know how to fill the ellipses.

Sorry if I missed the relevant part in the examples.

Can't pass string as it is

There's no way to declare a char* as an argument. At least, Larceny and Chez complain passing a string as a pointer.

So it's better to add string type.

Support specifying ABI properties for `foreign-procedure`

Currently there is no (?) way to specify additional ABI properties (calling convention, etc.) of foreign procedures in Chez (and other) implementation of pffi.

Chez supports those (here is the doc) and most of the time they are not really required to be able to build an FFI wrapper around C library. However, there is an exception to that, in particular, on MacOS X M1.

This comment in a Racket Chez branch mentions that in order to correctly set up a call for C procedure that uses va_list on an Apple Silicon architecture one needs to provide (__varargs_after X) ABI specifier.

Inability to specify it prevents akku Scheme package manager from working on M1 Mac OS - it binds to libcurl and uses curl_easy_setopt function that is actually a vararg-taking C func.

On the other hand, I'm not sure if any other Scheme implementation actually allows specifying ABI conventions so I wonder what would be the best way to add such support in a uniform way.

Problem with defining struct

I try to define the following struct:

struct tb_event {
	uint8_t type;
	uint8_t mod; /* modifiers to either 'key' or 'ch' below */
	uint16_t key; /* one of the TB_KEY_* constants */
	uint32_t ch; /* unicode character */
	int32_t w;
	int32_t h;
	int32_t x;
	int32_t y;
};

Here is what I have:

    (define-foreign-struct (tb-event make-tb-event tb-event?)
      (fields (uint8_t type tb-event-type)
              (uint8_t mod tb-event-mod)
              (uint16_t key tb-event-key)
              (uint32_t ch tb-event-ch)
              (int32_t w tb-event-w)
              (int32_t h tb-event-h)
              (int32_t x tb-event-x)
              (int32_t y tb-event-y)))

Chez scheme keep compaining:

$ scheme src/azul/main/editor.scm
Exception in define-foreign-struct: invalid define-foreign-struct ((fields (uint8_t type tb-event-type) (uint8_t mod tb-event-mod) (uint16_t key tb-event-key) (uint32_t ch tb-event-ch) (int32_t w tb-event-w) ...) (protocol (lambda args args))) in (define-foreign-struct (tb-event make-tb-event tb-event?) (fields (uint8_t type tb-event-type) (uint8_t mod tb-event-mod) (uint16_t key tb-event-key) (uint32_t ch tb-event-ch) (int32_t w tb-event-w) ...) (protocol (lambda args args))) near line 295, char 7 ...

Chez support?

Hi Kato! Is this project alive and might you consider adding support for Chez Scheme now that it's open source?

Auto-append file name extension in open-shared-object

Could open-shared-object auto-append the right file name extension if there is no #\. character in the filename given by the caller? E.g. (open-shared-object "libarchive") would open libarchive.dylib on MacOS, libarchive.so on Linux, libarchive.dll on Windows.

There's some code already to do that for Chez:

(case (machine-type)
  ((ta6le a6le i3le ti3le arm32le ppc32le) (load-shared-object "libc.so.6"))
  ((i3osx ti3osx a6osx ta6osx) (load-shared-object "libc.dylib"))
  ((ta6nt a6nt i3nt ti3nt) (load-shared-object "msvcrt.dll"))
  (else (load-shared-object "libc.so")))

I'm not sure what to do about the version numbers in the .so filenames.

Chez version returns pointers as integers

Hello,

Besides the missing machine types that I commented on separately on a commit, there is an error in how returned pointers are handled:

> (import (pffi))
> (define libc (open-shared-object "libc.so.6"))
> ((foreign-procedure libc pointer strerror (int)) 123)
140663955681195

Should it not be a pointer record rather than an integer?

Convenience for strings

Would it make sense to include these?

(define (utf8-pointer->string pointer)
  (and (not (= 0 (pointer->integer pointer)))
       (let loop ((n 0))
         (if (= 0 (pointer-ref-c-uint8 pointer n))
             (utf8->string (pointer->bytevector pointer n))
             (loop (+ n 1))))))

(define (string->utf8-pointer string)
  (let* ((bytes (string->utf8 string))
         (len (bytevector-length bytes))
         (bytes0 (make-bytevector (+ len 1) 0)))
    (bytevector-copy! bytes 0 bytes0 0 len)
    (bytevector->pointer bytes0)))

`bytevector->pointer` returns pointer with lifetime that is affected by garbage collection

Hi!

Thank you for the nice FFI library! I have a question related to bytevector->pointer implementation for Chez Scheme.

As it stands now, the procedure basically converts the bytevector to a pointer by calling a memmove pointer with zero size argument. To my understanding the purpose of this approach is to utilise Chez built-in conversion mechanisms to first convert the bytevector to u8* and then convert it via memmove to uptr. However, the lifetime of the retrieved pointer is something that I'm concerned about - the documentation for foreign-procedure states that (I omit non-relevant part):

u8*: The argument must be a Scheme bytevector or #f. ... . The bytevector should not be retained in foreign variables or data structures, since the memory management system may relocate or discard them between foreign procedure calls, and use their storage for some other purpose.

This means that the value returned by bytevector->pointer is not guaranteed to (correctly) survive a garbage collection. Since GC can kick at any time it means that the value cannot be reliably used/passed to C libraries.

As far as I can tell, the only way to make sure that returned pointer is valid always is to explicitly allocate memory (but then it has to be reclaimed).

So my question - am I missing something? If not, I can prepare a PR that addresses this issue using guardians and explicit copying of bytevector's data.

Removing C runtime dependency from Chez

This kind of trick may work on Chez

> (load-shared-object "msvcrt.dll")
> (define f (foreign-procedure "memmove" (u8* u8* size_t) uptr))
> (define (bytevector->pointer bv) (f bv bv (bytevector-length bv)))
> (bytevector->pointer #vu8(1 2 3 4))
1326944305800

This basically provides the same as the one I've written in C (may add some overheads, though).

Error message of define-foreign-struct is confusing (was: Callback as struct field raises exception)

I'm trying to define this in scheme:

struct gsl_function_struct 
{
  double (* function) (double x, void * params);
  void * params;
};

My attempt:

(define-foreign-struct gsl-function
  (fields ((callback double (double pointer))  function)
          (pointer params)))

Chez gives Exception in symbol->string: (callback double (double pointer)) is not a symbol. However, (symbol->string (callback double (double pointer))) works fine. Is this expected?

build failure

Running make prepare-guile followed by make guile (guile 2.011 installed) fails with:

make guile
cd tests; gcc -fPIC -shared -Wall -o functions.so functions.c
echo (set! %load-extensions '(".guile.sls" ".sls" ".scm")) > .guile.rc
LD_LIBRARY_PATH=:tests; guile --no-auto-compile -l .guile.rc -L src tests/test.scm
%%%% Starting test PFFI (Writing full log to "PFFI.log")
Backtrace:
In ice-9/boot-9.scm:
157: 10 [catch #t #<catch-closure 28133a0> ...]
In unknown file:
?: 9 [apply-smob/1 #<catch-closure 28133a0>]
In ice-9/boot-9.scm:
63: 8 [call-with-prompt prompt0 ...]
In ice-9/eval.scm:
432: 7 [eval # #]
In ice-9/boot-9.scm:
2401: 6 [save-module-excursion #<procedure 2833780 at ice-9/boot-9.scm:4045:3 ()>]
4052: 5 [#<procedure 2833780 at ice-9/boot-9.scm:4045:3 ()>]
1724: 4 [%start-stack load-stack ...]
1729: 3 [#<procedure 284bb70 ()>]
In unknown file:
?: 2 [primitive-load "/home/erje/builds/ffi/r6rs-pffi-master/tests/test.scm"]
In ice-9/eval.scm:
453: 1 [eval # ()]
In unknown file:
?: 0 [dynamic-link "functions.so"]

ERROR: In procedure dynamic-link:
ERROR: In procedure dynamic-link: file: "functions.so", message: "file not found"
Makefile:42: recipe for target 'guile' failed
make: *** [guile] Error 1

Guidance for enums

Hi,

I am just playing/exploring, but I love this library!
A question came up when I was trying to do a minimal hello world example with gtk+.
How would we represent foreign enums, like GTK_WINDOW_TOPLEVEL?
I know I can pass an int corresponding to the value of the enum, but I'm interested in the more idomatic, correct way to do this in pffi. Thanks!

Running compiled code with Petite Chez Scheme

Hello Takashi,

PFFI on Chez Scheme uses eval to get Chez's foreign-procedure and it's causing a small problem. My binary distributions of Akku.scm come bundled with Petite Chez Scheme, which doesn't have the compiler. I can compile Akku.scm just fine, but due to eval, I get this error: Exception in interpret: cannot compile foreign-procedure: compiler is not loaded.

It would be better if PFFI's foreign-procedure expanded to Chez's foreign-procedure and didn't need to use eval. I had a cursory glance at the code and it looks like make-c-function and make-c-callback in compat.chezscheme.sls can be written as syntax-case macros. What do you think?

Export null-pointer?

From compat.larceny.sls:

(define (null-pointer? pointer) (zero? (pointer->integer pointer)))

Might as well make this part of the public interface?

Links to examples

Can someone please add links to some real-world examples, e.g. for some popular C libraries?

Supporting varargs

At this moment, this library doesn't support varargs C function call.

How

Adding an extra marker ___ (as ... is already taken by syntax)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.