[plt-scheme] Using FFI with complex structures and input/output parameters?

From: Elena Garrulo (egarrulo at gmail.com)
Date: Tue Jun 30 08:41:33 EDT 2009

Hello,

I'm trying to wrap a Windows DLL using FFI.

I got past the simpler functions, but I'm getting lost when it comes
to input/output of complex structures.

I'm attaching a stripped down version of my code, which ends calling
the "SCardTransmit" function and fails with "zero?: expects argument
of type <real number>; given #<cpointer>".

I'd also like to know whether there is a way to automatically evaluate
C structures' size (currently I'm doing it manually).

Software:
- PLT Scheme 4.2;
- Windows XP SP3

Thank you very much.



;; CODE FOLLOWS

(require mzlib/foreign)
(unsafe!)


  (define winscard (ffi-lib "winscard"))

  (define _DWORD _int)
  (define _LONG _int)
  (define _SCARDHANDLE _int) ;; AN OPAQUE POINTER WOULD BE BETTER.

  (define 	+SCARD_PROTOCOL_T0+   #x0001) ;; T=0 active protocol.
  (define 	+SCARD_PROTOCOL_T1+   #x0002) ;; T=1 active protocol.
  (define 	+SCARD_PROTOCOL_ANY+   (bitwise-ior +SCARD_PROTOCOL_T0+
+SCARD_PROTOCOL_T1+))


  (define-cstruct _SCARD_IO_REQUEST ((dwProtocol _DWORD)
                                     (cbPciLength _DWORD)))

  (define +sizeof-SCARD_IO_REQUEST+ (+ (ctype-sizeof _DWORD)
                                       (ctype-sizeof _DWORD))) ;; Any
way to have it generated automatically?


#|
LONG SCardTransmit(
    IN     SCARDHANDLE hCard,
    IN     LPCSCARD_IO_REQUEST pioSendPci,
    IN     LPCBYTE pbSendBuffer,
    IN     DWORD cbSendLength,
    IN OUT LPSCARD_IO_REQUEST pioRecvPci, // It can be NULL.
    OUT    LPBYTE pbRecvBuffer,
    IN OUT LPDWORD pcbRecvLength);
|#
  (define SCardTransmit
    (get-ffi-obj "SCardTransmit"
                 winscard
                 (_fun (hCard : _SCARDHANDLE) ;; == IN SCARDHANDLE hCard
                       (pioSendPci : (_ptr i _SCARD_IO_REQUEST)) ;; ==
IN LPCSCARD_IO_REQUEST pioSendPci
                       (pbSendBuffer : (_vector i _byte)) ;; == IN
LPCBYTE pbSendBuffer
                       (_DWORD = (vector-length pbSendBuffer)) ;; ==
IN DWORD cbSendLength
                       (ioRecvPci : (_ptr io
_SCARD_IO_REQUEST-pointer/null)) ;; == IN OUT LPSCARD_IO_REQUEST
pioRecvPci
                       (pbRecvBuffer :  (_vector o _byte
cbRecvLength)) ;; == OUT LPBYTE pbRecvBuffer
                       (cbRecvLength : (_ptr io _DWORD)) ;; == IN OUT
LPDWORD pcbRecvLength
                       -> (error : _LONG)
                       )))




(SCardTransmit 1
                (make-SCARD_IO_REQUEST +SCARD_PROTOCOL_ANY+
+sizeof-SCARD_IO_REQUEST+)
                (make-vector 4 0)
                ;; cbSendLength AUTOMATICALLY GENERATED.
                #f ;; PASSING NULL.
                ;; pbRecvBuffer SKIPPED SENCE IS AN OUTPUT PARAMETER.
                4
                )


Posted on the users mailing list.