From: Bruce J. Weimer, MD
Subject: Shared Memory
Date: 
Message-ID: <0PWdncAOurMKDFuiRVn-jg@mminternet.net>
I'm trying to get at data that's in a "C" type structure in shared memory.
I can link to the shared memory, but I can't quite get at the structure -
here's what I have so far:

;;;;  TYPE DEFINITIONS
(fli:define-c-typedef fli-long :long)
(fli:define-c-typedef fli-dword :long)
(fli:define-c-typedef fli-bool (:boolean :int))
(fli:define-c-typedef fli-hwnd (:unsigned :long))
(fli:define-c-typedef fli-handle (:unsigned :long))
(fli:define-c-typedef fli-void (:pointer :void))

;;;;  I'M NOT SURE ABOUT THIS
;;;;  DEFINITION BUT IT SEEMS TO BE WORKING
(fli:define-c-typedef fli-lpctstr :pointer)



;;;;  THIS IS WHERE KERNAL32 IS ON MY COMPUTER
(fli:register-module :kernal32-dll :real-name
"C:\\WINDOWS\\system32\\Kernel32")


;;;;  THIS IS THE "C" DEFINITION FOR "OpenFileMapping"
;HANDLE OpenFileMapping(
;  DWORD dwDesiredAccess,  // access mode
;  BOOL bInheritHandle,    // inherit flag
;  LPCTSTR lpName          // pointer to name of file-mapping object
; )


;;;;  THIS IS MY FLI VERSION OF "OpenFileMapping"
;;;;  KERNAL32 EXTERNALIZES IT AS "OpenFileMappingW"
(fli:define-foreign-function
  (open-file-mapping "OpenFileMappingW")
  ((dwDesiredAccess  fli-dword)
   (bInheritHandle fli-bool)
   (lpName fli-lpctstr))
   :result-type fli-handle)


;;;;  THIS FUNCTION USES "OpenFileMapping"
;;;;  TO GET THE HANDLE TO SHARED MEMORY:SERVER1
(defun get-mem-handle (msg-name)
  (let ((mem-handle nil)
        (external-format (if (string= (software-type) "Windows NT")
     :unicode
     :ascii)))
       (fli:with-foreign-string (name-ptr element-count byte-count
    :external-format external-format)
  msg-name
  (declare (ignore element-count byte-count))
  (setf mem-handle (open-file-mapping 983071 nil name-ptr))
                :module :kernal32-dll)
       mem-handle))


;;;;  "hFileMapping" IS THEN THE HANDLE TO SHARED MEMORY:SERVER1
(setf hFileMapping (get-mem-handle "Server1"))



;;;;  THIS IS THE "C" DEFINITION FOR "MapViewOfFile"
;LPVOID MapViewOfFile(
;  HANDLE hFileMappingObject,  // file-mapping object to map into address
space
;  DWORD dwDesiredAccess,      // access mode
;  DWORD dwFileOffsetHigh,     // high-order 32 bits of file offset
;  DWORD dwFileOffsetLow,      // low-order 32 bits of file offset
;  DWORD dwNumberOfBytesToMap  // number of bytes to map
; );


;;;;  THIS IS MY FLI VERSION OF "MapViewOfFile"
;;;;  KERNAL32 EXTERNALIZES IT AS "MapViewOfFile"
(fli:define-foreign-function
  (map-view-of-file "MapViewOfFile")
  ((hFileMappingObject  fli-handle)
   (dwDesiredAccess fli-dword)
   (dwFileOffsetHigh fli-dword)
   (dwFileOffsetLow fli-dword)
   (dwNumberOfBytesToMap fli-dword))
   :result-type fli-void)


;;;;  THIS FUNCTION USES "MapViewOfFile" TO GET THE MAP's ADDRESS
(defun get-map-address (mem-handle)
  (map-view-of-file mem-handle 983071 0 0 0))



;;;;  "pSharedMem" IS THEN THE ADDRESS OF THE SHARED MEMORY
(setf pSharedMem (get-map-address hFileMapping))


;;;;  AND SO FAR SO GOOD  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; THEN THIS IS THE "C" DATA STRUCTURE IN SHARED MEMORY THAT I'M AFTER
;   struct msg
;   { DWORD seqnum;  //sequential number of message (new message flag)
;     DWORD timetag;  //time in millisec since computer start
;  DWORD cmd1;  //generic single word command messages
;  DWORD cmd2;
;  DWORD cmd3;
;  DWORD data1;  //generic single word data (e.g distances)
;  DWORD data2;
;  DWORD data3;
;  char  str1[121]; //generic string commands or data.
;  char  str2[121];
;  char  str3[121];
;   } msg1;

;;;;  THE "C" USERS ARE THEN DOING THIS
;;;;  memcpy(&msg1, pSharedMem, sizeof(msg))   //copy from shared memory

;;;;  BUT NOW I'M STUCK
;;;;  ISN'T THERE A STRAIGHT FORWARD WAY TO DO THIS IN LISP?

;;;;  FOR EXAMPLE, THIS SHOULD CREATE THE "MSG" STRUCTURE,
;;;;  BUT THEN HOW DOES THIS GET LINKED TO SHARED MEMORY?
(fli:define-c-struct msg
  (seqnum fli-dword)
  (timetag fli-dword)
  (cmd1 fli-dword)
  (cmd2 fli-dword)
  (cmd3 fli-dword)
  (data1 fli-dword)
  (data2 fli-dword)
  (data3 fli-dword)
  (str1 :char) ;BTW, ":CHAR" MIGHT NOT BE THE RIGHT "TYPE"
  (str2 :char) ;TO USE HERE SINCE THESE ARE STRINGS??
  (str3 :char))


;;;;  THIS SETS "my-msg" TO BE AN INSTANCE OF THE STRUCTURE
;(setq my-msg (fli:allocate-foreign-object :type 'msg))


;;;;  THIS THEN RETURNS THE VALUE OF THE "data1" SLOT
;(fli:foreign-slot-value my-msg 'data1)

Anyway, so that's where I am - any help or suggestions as to how I can get
at the data structure will be greatly appreciated.  And thanks in advance.

Bruce.