zythum Posted March 28, 2009 Report Share Posted March 28, 2009 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 '************************************************************************* Quote Link to comment
Rolf Kalbermatter Posted March 30, 2009 Report Share Posted March 30, 2009 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 Quote Link to comment
zythum Posted April 1, 2009 Author Report Share Posted April 1, 2009 QUOTE (rolfk @ Mar 29 2009, 03:21 AM) 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 I found http://forums.ni.com/ni/board/message?boar...ding&page=2 about a RegisterWindowMessageA. May be a good start? Quote Link to comment
Rolf Kalbermatter Posted April 1, 2009 Report Share Posted April 1, 2009 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 Quote Link to comment
zythum Posted April 2, 2009 Author Report Share Posted April 2, 2009 QUOTE (rolfk @ Mar 31 2009, 06:08 PM) 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 So, I need the reverse of "RegisterWindowMessage"? That's correct? If this is, may this could help http://groups.google.it/group/microsoft.pu...60bc4c43a844a37 ?Using GetClipboardFormatName as reported into "Community Content" on http://msdn.microsoft.com/en-us/library/ms644947(VS.85).aspx . RegisterWindowMessage is a alias of RegisterClipboardFormat Quote Link to comment
Rolf Kalbermatter Posted April 2, 2009 Report Share Posted April 2, 2009 QUOTE (zythum @ Apr 1 2009, 07:24 AM) So, I need the reverse of "RegisterWindowMessage"? That's correct? If this is, may this could help http://groups.google.it/group/microsoft.pu...60bc4c43a844a37 ?Using GetClipboardFormatName as reported into "Community Content" on http://msdn.microsoft.com/en-us/library/ms644947(VS.85).aspx . RegisterWindowMessage is a alias of RegisterClipboardFormat 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 Quote Link to comment
zythum Posted April 3, 2009 Author Report Share Posted April 3, 2009 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 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.