Shared Memory

From: Bruce J. Weimer, MD (weimer_at_mminternet.com)
Date: 11/28/03


Date: Thu, 27 Nov 2003 16:06:45 -0800

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.