LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

embed a 32-bit exe in a 64-bit LabVIEW app?

I am developing an application that is a special purpose 3D scanner that interfaces with a Keyence profiling laser to gather data.  Originally I built it in LabVIEW 64-bit because it deals with a large set of data and the 2Gb limit of 32-bit LabVIEW is marginal for larger scans, which results in a "Memory is full" error.  I think I have optimized the application for memory management by holding the data in single element queues and data value references and using the single rather than double data type. The most recent development is adding a USB microscope to the application but the problem is it is only supported with 32-bit SDK and uses a 32-bit ActiveX control, which of course doesn't work in 64 bit LabVIEW.  The main application launches several modular pieces including:

  • Keyence interface
  • stepper motor communication
  • camera interface
  • data analysis

I am currently presenting the Keyence, data analysis, and camera interface VI as plug-ins in a subpanel.  It works great in LabVIEW 32-bit but I run into memory limitations.  

 

My question is if anyone has an idea of how to mix the 32-bit camera with a 64 bit application.  Would it work to compile the camera code separately as a 32-bit exe and launch it using system exec from the main 64 bit app and then use the windows API to embed the app in a VI that my 64 bit app can present in a subpanel?  The subpanel VI would exchange user events with the main app and communicate with the 32-bit exe over TCP.  

 

I am struggling to get the windows API (user32.dll) to control built my built application.  I have downloaded Hoovah's "Main Insert Notepad example" in this post:

https://forums.ni.com/t5/LabVIEW/How-to-run-an-exe-as-a-window-inside-a-VI/td-p/3112435/page/3

 

but I suspect that LabVIEW built apps don't comply with Windows standards or something because it works with notepad but not my built application.  

 

An alternative would be to keep the main app in 32-bit for hardware control and launch the analysis as 64-bit as that is the memory hog.  

 

Please throw rocks or point out a better way if you can think of any.  Thanks in advance for your ideas.

0 Kudos
Message 1 of 13
(2,475 Views)

I have used that same technique I posted there, on LabVIEW applications.  But you are correct in that LabVIEW does some non-standard things with windows, because it needs to be cross platform.  As a result things like menu bars and title bars can't be removed like they could with that notepad example as easily.

 

If you do need the 64 bit memory space, then I think the best route is just to stay in 64 bit all the time.  There are techniques for calling 32 bit programs from 64 bit ones.  But all the cases I've seen them used are on relatively small amounts of data, not camera streams.  I have an example of this using Network Streams here.  But this is just calling 32 bit DLLs for some data, not any ActiveX controls.

 

I think the best chance for success is going to be to find 64 bit options and just stay in that environment.  I also didn't see what exactly the ActiveX portion is accomplishing for you.  If you just want to have it as a visual indicator of a camera, you might be able to get away with using VLCs.  Here is an example that I've used on a few different cases to display an IP camera, or a USB camera on a LabVIEW front panel.

 

I would hope that there are Keyence drivers, and stepper motor control, that work in 64 bit.

0 Kudos
Message 2 of 13
(2,468 Views)

Thanks for your quick response, Hooovahh.  The USB camera is a DinoLite USB microscope and I was able to utilize their SDK, which included a LabVIEW example built around an ActiveX control.  The ActiveX control provides a viewer on the front panel of the VI and the ActiveX reference has several convenient properties and methods for things like setting the capture rate, auto-scaling the image, turning the LED lights on/off, saving a frame as a JPG.  I have adapted my VI from the example from DinoLite in their SDK but its only viable in the 32-bit environment.

 

I simply insert the camera VI into a subpanel in my main app in the 32 bit environment.  Attached is a screenshot of the block diagram of just the camera VI.  It's pretty simple.

 

Thanks so much for your ideas.  I'll think about how I could use network streams.  

 

 

0 Kudos
Message 3 of 13
(2,433 Views)

Yeah I think that VLC should be able to accomplish that, which should work in 64 bit.  Getting the USB settings right does take some trial and error, but VLC works with such a large variety of codecs I'd expect it to be possible.

0 Kudos
Message 4 of 13
(2,426 Views)

I have switched to a 64-bit compatible camera and I believe VLC is the solution.  Thanks for the suggestion.  I have the 64-bit version of VLC installed and it works with my camera. I am trying the "VLC-LabVIEW Embedded.vi" from the example that you suggested but cannot seem to get past the libvlc_media_new_path function without error.  I think I have a dependency issue but not sure where to go from here. I downloaded the source code for VLC just to obtain the header file so that I could investigate with the Import Shared Library wizard in LabVIEW.  The results of the import process are successful for 22 functions but libvlc_media_new_path is among those that fail to import.

jjbloomfield_0-1657288095249.png

jjbloomfield_1-1657288249769.png

I don't know if you've ever used Dependency Walker as a tool to investigate dll dependencies but it indicates that many dependencies are missing in my installation:

jjbloomfield_2-1657289391073.png

If you have any ideas about where to go from here, I'd appreciate it.

 

 

0 Kudos
Message 5 of 13
(2,375 Views)

Trying to debug shared library problems by using the Import Library Wizard is almost like trying to use a sledge hammer since you have trouble in applying a scalpel for precision surgery. Highly useless!

 

The Import Library Wizard is a handy tool to help with the very repetitive work of creating wrapper VIs for a larger amount of shared library functions. It is NOT and can NOT be a precision tool to get all the intricacies of trying to correctly interface to shared library functions. After the Import Library Wizard has done its magic an experienced programmer has to go through each and every single created VI and verify and often modify the created VIs to apply the correct programming logic and/or make the VI interface for the user more LabVIEW savvy by hiding C programming complications in the VI.

 

The shared library interface is build around calling C functions and assumes that the programmer using those functions has a great deal of knowledge about interfacing to C functions in general, about proper buffer management handling and the specific API in question. Much of that information can NOT be put in the header file for a shared library, but is either contained in the hopefully extensive prosa documentation for that library or must be brought in by the experience of the programmer and his/her ability to deduce common patterns from things like naming conventions of parameters and functions. All these are things that an automated tool like the Import Library Wizard simply can't do unless you find a magic wand that can somehow put the ghost into it. I haven't found that magic wand yet and know of nobody who has. 😀

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 6 of 13
(2,369 Views)

Hi Rolf:

I was trying to discern if I have a dependency/installation problem or simply a syntax issue.  I thought it was a clue that I may have a dependency/installation problem and not simply a syntax issue with the input argument of the erring function when the first erring function in the VI was among those that would not import in the wizard.  One of the functions that successfully imports in the wizard runs without error but the next call into the same dll is a function that does not import.  However, perhaps this is a red herring as you suggest.

0 Kudos
Message 7 of 13
(2,365 Views)

It's maybe not a red herring but a so called reverse conclusion. When the Import Library Wizard indicates that it can not import a certain function it can have a number of reasons.

 

For instance the function may be exported from the DLL but there is no definition in the header file that can be matched with it, maybe because there is a strange name decoration employed in the exported function, but usually because it is not declared in the header files that you pointed the import library wizard to, or simply because it is an undocumented function in the shared library for the developers private use.

 

Another often occuring reason is when the function uses complex datatypes that the Import Library Wizard isn't prepared to deal with. For instance structures with pointers or typeless pointers. The Import Library Wizard doesn't support them because they are either very difficult to import correctly or simply impossible to do without more information that can not be deduced from the declaration in the header file.

 

So someone had to do those functions themselves by hand. And that someone might not have understood all the difficulties of these functions, that the Import Library Wizard preventively threw its hands into the air and refused to try to import.

 

The Dependency Walker you try to use, was a handy tool back in the days when Microsoft Windows was 32-bit only on every possible computer that you could encounter. But it hasn't learned about the difficulties of 32-bit and 64-bit DLLs and the differences with them. So if you try to look at a DLL that uses a different bitness than what the Dependency Walker and the Windows system you try to run it on use, it gets utterly confused and will generally claim that it can't find any of the dependencies. Which is of course total nonsense for DLLs like advapi.dll, kernel32.dll or user32.dll. If your Windows system couldn't find them it could not even start up properly!

 

So in order to get a somewhat more useful overview about dependencies you should use a different tool. I usually use this one. It isn't completely perfect either but it works pretty well and definitely a lot better than Dependency Walker. That said, I can't see your assumption that you have a dependency problem confirmed in the Dependency Walker screen you show. All the DLLs that Dependency Walker shows in there are standard Windows DLLs that for sure are present on any modern Windows system and both for 32-bit and 64-bit.

 

It doesn't mean that there couldn't be dependency problems but you won't be able to see them with a dependency checker like this. If the VLC DLL dynamically loads additional DLLs at startup or as needed when you call certain functions in the library, a static dependency checker tool can't show those dependencies at all. The only way to see these is by running everything with an attached debugger that will capture any Windows debug output when your DLL tries to dynamically load DLLs that Windows can't find. Of course the function that tries to load such dependencies should check that the loading was successful and return an according error code if it wasn't, but that depends entirely on the safety of the library developer. I have seen many libraries which only return a generic error code on such errors, or no error code at all but simply don't work. And sometimes they don't even try to check if the loading was successful but simply try to call the non existent function and fatally crash.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 8 of 13
(2,358 Views)

Rolf:

 

Thanks for the suggestion on the dependency tool.  It loads the libvlc.dll file successfully.

 

I think I just discovered that all the i32 datatypes in the dll function calls from the original example VI need to be 64 bit instead of 32 bit.  Now, the function calls seem to execute without returning the exception error.

This post pointed me in that direction.

 

John B.

0 Kudos
Message 9 of 13
(2,335 Views)

@jjbloomfield wrote:

Rolf:

 

Thanks for the suggestion on the dependency tool.  It loads the libvlc.dll file successfully.

 

I think I just discovered that all the i32 datatypes in the dll function calls from the original example VI need to be 64 bit instead of 32 bit.  Now, the function calls seem to execute without returning the exception error.

This post pointed me in that direction.


That is a very unspecific advice and generally not correct. It depends what the underlaying C type is. If it is an explicit 32-bit variable, then changing everything to 64-bit in the best case is wasteful, but could also cause real trouble. It depends very much on what the undrelaying C datatype is. Anything that is a pointer or resembles a pointer in some way needs to be changed but not unconditionally to 64-bit. Instead you should choose the pointer sized integer type in the Call Library Node. The LabVIEW wire itself will indeed need to be 64-bit since LabVIEW uses a strict type system that does not allow for variable sized datatypes (except when you use Variants, which however is an entirely different thing).

 

But by making the Call Library Node Parameter a pointer sized integer you can continue to use the same VIs for 32-bit and 64-bit DLLs. LabVIEW will automatically convert the 64-bit integer to whatever the pointer size is for the current environment and back afterwards. By configuring pointer sized parameters as always 64bit integer in the Call Library Node would make the VIs cause problems when run in 32-bit LabVIEW with a 32-bit DLL.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 10 of 13
(2,324 Views)