Jump to content

File Mapping with LabView


Recommended Posts

Hi,

I need to transfer information between a outside software and a LabView software. I take a look over http://forums.ni.com/ni/board/message?boar...=179626#M108830 about "Accessing shared memory location", but the documentation is not really present. I got a example in VB. But, I don't really understand how to preceded.

I understand that I need to read a 2d array (320*240, 16bit) into memory (an image). But, I don't know how what to send to user32.dll / kernel32.dll

Thank you for your advice

"How it Works

Thermalyze creates a named file mapping object and then maps a view of the file in its own virtual address space in order to write image data to a file that is stored in physical memory. Immediately after writing a new image to the file, Thermalyze sends a Windows message to the client program to notify the client program that a new image is available. If there are no processing delays, images are written at a maximum rate of 30 images per second.

In order for a client program to read the image data from the file, the client must open the named file mapping object created by Thermalyze using the name “OptoThermFileMapObject” and then map a view of the file in its own virtual address space. In order to receive Windows messages indicating that a new image is available, the client must register the custom window message by the name “OptoThermNewImageReady”. The client must then subclass its top level window by replacing the window’s standard window procedure with a custom procedure so that the message can be detected.

"

File Mapping - Visual Basic 6 Example

Code located in client application’s top-level form:

'*************************************************************************

Private Sub Form_Load()

SetNewWindowProcedure hWnd

GetMessageIdentifier

End Sub

Private Sub Form_Unload(Cancel As Integer)

SetOldWindowProcedure hWnd

UnmapAndCloseHandles

End Sub

'*************************************************************************

Code located in client application’s module:

'constants used in API functions and subs

'*************************************************************************

'sets a new address for the window procedure

Private Const GWL_WNDPROC = -4

'320 columns x 240 rows x 2 bytes = 153600 bytes

Private Const FILE_MAP_SIZE = 153600

Private Const FILE_MAP_NAME = "OptoThermFileMapObject"

Private Const FILE_MAP_MESSAGE_NAME = "OptoThermNewImageReady"

Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000

Private Const SECTION_QUERY As Long = &H1

Private Const SECTION_MAP_WRITE As Long = &H2

Private Const SECTION_MAP_READ As Long = &H4

Private Const SECTION_MAP_EXECUTE As Long = &H8

Private Const SECTION_EXTEND_SIZE As Long = &H10

Private Const SECTION_ALL_ACCESS As Long =

STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or

SECTION_MAP_WRITE Or SECTION_MAP_READ Or

SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE

Private Const FILE_MAP_ALL_ACCESS As Long = SECTION_ALL_ACCESS

'*************************************************************************

'windows API functions and subs

'*************************************************************************

'subclassing API functions

Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long,ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long 'file mapping API functions

Private Declare Function OpenFileMapping Lib "kernel32.dll" Alias "OpenFileMappingA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long

Private Declare Function MapViewOfFile Lib "kernel32.dll" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long

Private Declare Function UnmapViewOfFile Lib "kernel32.dll" (ByRef lpBaseAddress As Any) As Long

Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long

'API functions to aid with working with mapped file view

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Long, pSrc As Long, ByVal ByteLen As Long)

Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long

Private Declare Function SafeArrayAccessData Lib "Oleaut32" (ByVal psa As Long, pvData As Long) As Long

Private Declare Function SafeArrayUnaccessData Lib "Oleaut32" (ByVal psa As Long) As Long

Private Declare Sub RtlMoveMemory2 Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByVal Source As Long, ByVal Length As Long)

'*************************************************************************

'public variables

'*************************************************************************

Public g_OldWindowProcedureHandle As Long

Public g_MessageIdentifier As Long

'*************************************************************************

'private variables

'*************************************************************************

Private p_FileMapHandle As Long

Private p_MapViewAddress As Long

Private p_count As Long

'*************************************************************************

'subclassing the main window

'a new windows procedure must be created to evaluate the windows messages

'that are sent to the window

'*************************************************************************

Public Sub SetNewWindowProcedure(ByVal windowHandle As Long) g_OldWindowProcedureHandle = SetWindowLong(windowHandle, GWL_WNDPROC, AddressOfNewWindowProcedure)

End Sub

Public Function NewWindowProcedure(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

If (wMsg = g_MessageIdentifier) Then

'open the named file mapping object, map a view, and then process the new image

ReadMapView

Exit Function

End If

'continue normal processing of messages. VERY IMPORTANT!

NewWindowProcedure = CallWindowProc(g_OldWindowProcedureHandle, hWnd, wMsg, wParam, lParam)

End Function

Public Sub SetOldWindowProcedure(ByVal windowHandle As Long) SetWindowLong windowHandle, GWL_WNDPROC, g_OldWindowProcedureHandle

End Sub

'*************************************************************************

'get the custom message identifier

'*************************************************************************

Public Sub GetMessageIdentifier()

g_MessageIdentifier = RegisterWindowMessage(FILE_MAP_MESSAGE_NAME)

End Sub

'*************************************************************************

'open the named file mapping object, map a view, and then process

the new image

'*************************************************************************

Public Sub ReadMapView()

Dim myIntegerArray(320, 240) As Integer

Dim myVariantArray As Variant

Dim safeArrayPointer As Long

Dim arrayDataPointer As Long

Dim returnValue As Long

'open file mapping and then map view of file

If (p_FileMapHandle = 0) Then

p_FileMapHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, False, FILE_MAP_NAME)

If (p_FileMapHandle = 0) Then

'the file map has not been created yet

Exit Sub

Else

p_MapViewAddress = MapViewOfFile(p_FileMapHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0)

End If

End If

If (p_MapViewAddress = 0) Then

'the map view could not be created

Exit Sub

End If

'SAFEARRAY

'Visual Basic stores arrays in a SAFEARRAY data type which, in addition to the array

'data includes information on the array size and dimensions. Accessing the data in a

'SAFEARRAY is most safely done by working with windows API functions

'set safeArrayPointer to the address of the SAFEARRAY

'if the array is an integer type

CopyMemory safeArrayPointer, ByVal VarPtrArray(myIntegerArray()), 4

'if the array is a variant type, the address of the SAFEARRAY is 8 bytes after the

'address of the array

ReDim myVariantArray(320, 240) As Integer

CopyMemory safeArrayPointer, ByVal VarPtrArray(myVariantArray) + 8, 4

'set arrayDataPointer to the address off the array data

returnValue = SafeArrayAccessData(safeArrayPointer, arrayDataPointer)

'move the data from the map view to the address in arrayDataPointer

RtlMoveMemory2 ByVal arrayDataPointer, p_MapViewAddress, FILE_MAP_SIZE

End Sub

'must unmap view and close handles

Public Sub UnmapAndCloseHandles()

If (UnmapViewOfFile(p_MapViewAddress) = 0) Then

If (CloseHandle(p_FileMapHandle) <> 0) Then p_FileMapHandle = 0

End If

End Sub

'*************************************************************************

Link to comment

QUOTE (zythum @ Mar 27 2009, 11:33 AM)

Hi,

I need to transfer information between a outside software and a LabView software. I take a look over http://forums.ni.com/ni/board/message?boar...=179626#M108830 about "Accessing shared memory location", but the documentation is not really present. I got a example in VB. But, I don't really understand how to preceded.

I understand that I need to read a 2d array (320*240, 16bit) into memory (an image). But, I don't know how what to send to user32.dll / kernel32.dll

Thank you for your advice

"How it Works

Thermalyze creates a named file mapping object and then maps a view of the file in its own virtual address space in order to write image data to a file that is stored in physical memory. Immediately after writing a new image to the file, Thermalyze sends a Windows message to the client program to notify the client program that a new image is available. If there are no processing delays, images are written at a maximum rate of 30 images per second.

In order for a client program to read the image data from the file, the client must open the named file mapping object created by Thermalyze using the name "OptoThermFileMapObject" and then map a view of the file in its own virtual address space. In order to receive Windows messages indicating that a new image is available, the client must register the custom window message by the name "OptoThermNewImageReady". The client must then subclass its top level window by replacing the window's standard window procedure with a custom procedure so that the message can be detected.

"

File Mapping - Visual Basic 6 Example

Code located in client application's top-level form:

'*************************************************************************

Private Sub Form_Load()

SetNewWindowProcedure hWnd

GetMessageIdentifier

End Sub

Private Sub Form_Unload(Cancel As Integer)

SetOldWindowProcedure hWnd

UnmapAndCloseHandles

End Sub

'*************************************************************************

Code located in client application's module:

'constants used in API functions and subs

'*************************************************************************

'sets a new address for the window procedure

Private Const GWL_WNDPROC = -4

'320 columns x 240 rows x 2 bytes = 153600 bytes

Private Const FILE_MAP_SIZE = 153600

Private Const FILE_MAP_NAME = "OptoThermFileMapObject"

Private Const FILE_MAP_MESSAGE_NAME = "OptoThermNewImageReady"

Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000

Private Const SECTION_QUERY As Long = &H1

Private Const SECTION_MAP_WRITE As Long = &H2

Private Const SECTION_MAP_READ As Long = &H4

Private Const SECTION_MAP_EXECUTE As Long = &H8

Private Const SECTION_EXTEND_SIZE As Long = &H10

Private Const SECTION_ALL_ACCESS As Long =

STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or

SECTION_MAP_WRITE Or SECTION_MAP_READ Or

SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE

Private Const FILE_MAP_ALL_ACCESS As Long = SECTION_ALL_ACCESS

'*************************************************************************

'windows API functions and subs

'*************************************************************************

'subclassing API functions

Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long,ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long 'file mapping API functions

Private Declare Function OpenFileMapping Lib "kernel32.dll" Alias "OpenFileMappingA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long

Private Declare Function MapViewOfFile Lib "kernel32.dll" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long

Private Declare Function UnmapViewOfFile Lib "kernel32.dll" (ByRef lpBaseAddress As Any) As Long

Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long

'API functions to aid with working with mapped file view

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Long, pSrc As Long, ByVal ByteLen As Long)

Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long

Private Declare Function SafeArrayAccessData Lib "Oleaut32" (ByVal psa As Long, pvData As Long) As Long

Private Declare Function SafeArrayUnaccessData Lib "Oleaut32" (ByVal psa As Long) As Long

Private Declare Sub RtlMoveMemory2 Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByVal Source As Long, ByVal Length As Long)

'*************************************************************************

'public variables

'*************************************************************************

Public g_OldWindowProcedureHandle As Long

Public g_MessageIdentifier As Long

'*************************************************************************

'private variables

'*************************************************************************

Private p_FileMapHandle As Long

Private p_MapViewAddress As Long

Private p_count As Long

'*************************************************************************

'subclassing the main window

'a new windows procedure must be created to evaluate the windows messages

'that are sent to the window

'*************************************************************************

Public Sub SetNewWindowProcedure(ByVal windowHandle As Long) g_OldWindowProcedureHandle = SetWindowLong(windowHandle, GWL_WNDPROC, AddressOfNewWindowProcedure)

End Sub

Public Function NewWindowProcedure(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

If (wMsg = g_MessageIdentifier) Then

'open the named file mapping object, map a view, and then process the new image

ReadMapView

Exit Function

End If

'continue normal processing of messages. VERY IMPORTANT!

NewWindowProcedure = CallWindowProc(g_OldWindowProcedureHandle, hWnd, wMsg, wParam, lParam)

End Function

Public Sub SetOldWindowProcedure(ByVal windowHandle As Long) SetWindowLong windowHandle, GWL_WNDPROC, g_OldWindowProcedureHandle

End Sub

'*************************************************************************

'get the custom message identifier

'*************************************************************************

Public Sub GetMessageIdentifier()

g_MessageIdentifier = RegisterWindowMessage(FILE_MAP_MESSAGE_NAME)

End Sub

'*************************************************************************

'open the named file mapping object, map a view, and then process

the new image

'*************************************************************************

Public Sub ReadMapView()

Dim myIntegerArray(320, 240) As Integer

Dim myVariantArray As Variant

Dim safeArrayPointer As Long

Dim arrayDataPointer As Long

Dim returnValue As Long

'open file mapping and then map view of file

If (p_FileMapHandle = 0) Then

p_FileMapHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, False, FILE_MAP_NAME)

If (p_FileMapHandle = 0) Then

'the file map has not been created yet

Exit Sub

Else

p_MapViewAddress = MapViewOfFile(p_FileMapHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0)

End If

End If

If (p_MapViewAddress = 0) Then

'the map view could not be created

Exit Sub

End If

'SAFEARRAY

'Visual Basic stores arrays in a SAFEARRAY data type which, in addition to the array

'data includes information on the array size and dimensions. Accessing the data in a

'SAFEARRAY is most safely done by working with windows API functions

'set safeArrayPointer to the address of the SAFEARRAY

'if the array is an integer type

CopyMemory safeArrayPointer, ByVal VarPtrArray(myIntegerArray()), 4

'if the array is a variant type, the address of the SAFEARRAY is 8 bytes after the

'address of the array

ReDim myVariantArray(320, 240) As Integer

CopyMemory safeArrayPointer, ByVal VarPtrArray(myVariantArray) + 8, 4

'set arrayDataPointer to the address off the array data

returnValue = SafeArrayAccessData(safeArrayPointer, arrayDataPointer)

'move the data from the map view to the address in arrayDataPointer

RtlMoveMemory2 ByVal arrayDataPointer, p_MapViewAddress, FILE_MAP_SIZE

End Sub

'must unmap view and close handles

Public Sub UnmapAndCloseHandles()

If (UnmapViewOfFile(p_MapViewAddress) = 0) Then

If (CloseHandle(p_FileMapHandle) <> 0) Then p_FileMapHandle = 0

End If

End Sub

'*************************************************************************

While File Mappings aren't that difficult, the Windows API to deal with that is a bit more complex then just accessing a single function. So this part while in theory possible to be dealt with directly from the diagram using the Call Library Node is actually better handled in an external C DLL, that deals with these problems directly and offers LabVIEW a clean and easy to access interface.

The real killer however is the Windows message handling that is required. To implement that in LabVIEW only is not possible, since there is no way for you as LabVIEW programmer to intercept specific Windows messages. There is a Windows_Message_Queue example on the NI site that offers a C++ DLL to do that, but it is not exactly for what you need and you will have to modify it to work for your purposes. So I would simply create a complete new DLL and put everything in there. If I would have to do that I would estimate about 1 day of work for this to get a reliably working DLL and two or three LabVIEW VIs to access this. Now I do have a lot of experience with external C code integration in LabVIEW, so if you are gonna do that expect to have quite a bit longer for this and be willing to learn C to a level that goes well beyond beginners level.

Rolf Kalbermatter

Link to comment

QUOTE (zythum @ Mar 31 2009, 03:26 PM)

I found http://forums.ni.com/ni/board/message?boar...ding&page=2 about a RegisterWindowMessageA. May be a good start?

Yes a good start but the most easy thing of all. That example is about posting a message to another application. That is simple, even trivial. You need to wait for a message from the other applciation, that is a lot more involved.

Rolf Kalbermatter

Link to comment

QUOTE (zythum @ Apr 1 2009, 07:24 AM)

No you do call RegisterWindowMessage() but then you do not call SendMessage() but you have to receive that message from the other application and that requires at least intercepting the internal LabVIEW message queue (example I pointed out earlier) but since it is a system message maybe even installing a real Winddows message hook. While the Windows Message Queue example I mentioned earlier would help you with the first, you will have to REALLY write a C code DLL to do the second.

Rolf Kalbermatter

Link to comment

QUOTE (rolfk @ Apr 1 2009, 12:10 PM)

No you do call RegisterWindowMessage() but then you do not call SendMessage() but you have to receive that message from the other application and that requires at least intercepting the internal LabVIEW message queue (example I pointed out earlier) but since it is a system message maybe even installing a real Winddows message hook. While the Windows Message Queue example I mentioned earlier would help you with the first, you will have to REALLY write a C code DLL to do the second.

Rolf Kalbermatter

Thank; I will try to do a dll for that

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.