From: ······@bridgetrix.com
Subject: Foreign Function Interface in Corman Lisp
Date: 
Message-ID: <ncohen-1806991307540001@max5-77.ip.realtime.net>
   
I�m having problems connecting a Visual C++ interface and some Lisp code,
partly because of skimpy documentation in Corman Lisp and mostly because I
don�t know C++ and general principles of foreign function interface.  
Corman Lisp can create Lisp functions which can be called by C++ programs,
and pointers to those functions.   I have two questions:

   1. How do you use the pointer in C++ to actually call the Lisp
function.  Suppose x is the pointer, and the function has two arguments. 
Is that the construction:

             (*x) (arg1, arg2)       ?   

   Suppose the pointer were stored in a C++ array, say as the 0th value. 
Would the function call be the C++ equivalent of :

              ( * svref(array 0)) (arg1, arg2)

2.  How is the pointer passed to the C++ program?   If both of the
following methods work,  which is better? 

     a. Corman Lisp has an example of calling a C++ function from Lisp. 
Would this work:

         i. Define a C++ function, store_values, which stores its
arguments in an array, ARR.
         ii.  In the Lisp program, after the desired pointers to Lisp
foreign functions are created, put in a call to store_values with the
pointers as args.  

         Store_values would be declared EXTERN.  Would that also be true
for the array?

    b.  Corman Lisp has an example of Lisp code doing C-like things,
including allocating space for an array and storing the value of a foreign
function pointer in the array.   The relevant snippet is:

   (setf (cref WNDCLASSEX wndclass lpfnWndProc) (get-callback-procinst
'WndProc-devcaps1)) 

WndProc-devcaps1 is a Lisp function which can be called by C++, and
get-callback-procinst returns the pointer to the function.  Unfortunately,
neither �WNDCLASSEX�  nor �lpfnWndProc� is defined in the file.  What are
they?  Is the first an external C++ array? What�s �lpfnWndProc�?  wndclass
is defined:
   (let
     ...
   (wndclass (ct:malloc (sizeof 'WNDCLASSEX)))

What has to be in the C++ program for this to work?  For completeness, the
file in which this snippet appeared is included.   It appeared in the last
function, WinMain-devcaps1.  

;;;; 
;;;;  File:    devcaps1.lisp 
;;;;  Contents:   Simple Windows demonstration app, from Petzold's 
;;;;           Programming Windows 95 
;;;; 
(in-package :win32) 
 
(defconstant szAppName "DevCaps1") 
 
(defstruct info index label desc) 
 
(defvar *devcaps* 
   (list 
      (make-info :INDEX HORZSIZE    :LABEL "HORZSIZE" :DESC "Width in
millimeters:") 
     
          ;;;Many other entries omitted.  
)) 
 
(defvar *ps* nil) 
(defvar *tm* nil) 
 
(ct:defun-callback WndProc-devcaps1 ((hwnd HWND)(iMsg UINT)(wParam
WPARAM)(lParam LPARAM)) 
   ;;Rest of function definition omitted.  The Ct:defun-callback ;;defines
a Lisp function that can be called from C++.  This ;;function definition
doesn�t use the undefined terms above -- ;;WNDCLASSEX and lpfnWndProc
 
(defun WinMain-devcaps1 (hInstance hPrevInstance szCmdLine iCmdShow) 
   (let ((hwnd NULL) 
        (msg (ct:malloc (sizeof 'MSG))) 
        (wndclass (ct:malloc (sizeof 'WNDCLASSEX))) 
        (*ps* (ct:malloc (sizeof 'PAINTSTRUCT))) 
        (*tm* (ct:malloc (sizeof 'TEXTMETRIC)))) 
 
      (setf (cref WNDCLASSEX wndclass cbSize) (sizeof 'WNDCLASSEX)) 
      (setf (cref WNDCLASSEX wndclass style) (logior CS_HREDRAW CS_VREDRAW)) 
      (setf (cref WNDCLASSEX wndclass lpfnWndProc) (get-callback-procinst
'WndProc-devcaps1)) 
      (setf (cref WNDCLASSEX wndclass cbClsExtra) 0) 
      (setf (cref WNDCLASSEX wndclass cbWndExtra) 0) 
      (setf (cref WNDCLASSEX wndclass hInstance) hInstance) 
      (setf (cref WNDCLASSEX wndclass hIcon) (LoadIcon NULL IDI_APPLICATION)) 
      (setf (cref WNDCLASSEX wndclass hCursor) (LoadCursor NULL IDC_ARROW)) 
      (setf (cref WNDCLASSEX wndclass hbrBackground) (GetStockObject
WHITE_BRUSH)) 
      (setf (cref WNDCLASSEX wndclass lpszMenuName) NULL) 
      (setf (cref WNDCLASSEX wndclass lpszClassName) (ct:create-c-string
szAppName)) 
      (setf (cref WNDCLASSEX wndclass hIconSm) (LoadIcon NULL IDI_APPLICATION)) 
      (RegisterClassEx wndclass) 
      (setq ghwnd  
         (CreateWindowEx 0 
            (ct:create-c-string szAppName)            ;; window class name 
            (ct:create-c-string "Device Capabilities")   ;; window caption 
            WS_OVERLAPPEDWINDOW                    ;; window style 
            CW_USEDEFAULT                       ;; initial x position 
            CW_USEDEFAULT                       ;; initial y position 
            CW_USEDEFAULT                       ;; initial x size 
            CW_USEDEFAULT                       ;; initial y size 
            (cl::get-application-main-window)         ;; parent window handle 
            NULL                             ;; window menu handle 
            hInstance                           ;; program instance handle 
            NULL))                              ;; creation parameters 
 
      (ShowWindow ghwnd iCmdShow) 
      (UpdateWindow ghwnd) 
      (do ((ret (GetMessage msg NULL 0 0)(GetMessage msg NULL 0 0))) 
         ((not ret)) 
         (TranslateMessage msg) 
         (if (= (cref MSG msg message) WM_QUIT) 
            (return)) 
         (DispatchMessage msg)) 
 
      (cref MSG msg wParam))) 
 
(defun test-devcaps1 () 
   (setq instance (cl::get-application-instance)) 
   (winmain-devcaps1 instance null (ct:create-c-string "") SW_SHOW)) 
 

  Thanks.

   Neil

Neil Cohen
Bridge Trix
Producers of the Bobby Wolff Bridge Mentoring Series
http://www.bridgetrix.com

From: Vassili Bykov
Subject: Re: Foreign Function Interface in Corman Lisp
Date: 
Message-ID: <u7loxjq4f.fsf@objectpeople.com>
······@bridgetrix.com writes:

> I�m having problems connecting a Visual C++ interface and some Lisp code,
> partly because of skimpy documentation in Corman Lisp and mostly because I
> don�t know C++ and general principles of foreign function interface.
> [...]

Neil, you are right in that to do what you want, you have to be
familiar with C (the questions you ask are not C++ specific) and
Windows API concepts.  You do not have to be a wizard, but knowing C
data types and their machine representation, function calling
convention, and what is WNDCLASSEX are among the things that should be
sort of obvious.  If you are serious about interfacing with C and
doing some Windows API programming, you cannot avoid studying that.
Your best bet would be to get a book or two and study some C
programming and Windows API.  If you still have questions after you've
done so, that would at least help you formulate them properly.  Beyond
C basics, there are not too many FFI principles that are not apparent
from reading sys\ffi.lisp.

Hope this helps,

--Vassili
From: Dan L. Pierson
Subject: Re: Foreign Function Interface in Corman Lisp
Date: 
Message-ID: <37709f7a.61552453@news.randori.com>
Vassili Bykov <·······@objectpeople.com> wrote:

> ······@bridgetrix.com writes:
> 
> > I�m having problems connecting a Visual C++ interface and some Lisp code,
> > partly because of skimpy documentation in Corman Lisp and mostly because I
> > don�t know C++ and general principles of foreign function interface.
> > [...]
> 
> Neil, you are right in that to do what you want, you have to be
> familiar with C (the questions you ask are not C++ specific) and
> Windows API concepts.  You do not have to be a wizard, but knowing C
[snip]
> Your best bet would be to get a book or two and study some C
> programming and Windows API.  If you still have questions after you've

I strongly recommend "Win32 Programming", by Brent E. Rector and
Joseph M. Newcomer, ISBN 0-201-63492-9.  Not a C beginner's book but
_very_ complete and detailed on all the screwy Win32 bits.

This is now way off topic, so we should probably drop it...
Dan Pierson, Control Technology Corporation
···@control.com