10-07-2024 03:01 AM - edited 10-07-2024 03:13 AM
Well, my library interfaces with the Open62541 library which is a comprehensive OPC UA implementation. And this library returns data in a binary format that is not directly interfaceable to LabVIEW through the Call Library Node at all. So I have to write an intermediate wrapper shared library (DLL) in C to translate between the two. And while supporting all the different datatypes is quite a bit of repetitive work on the LabVIEW side, it is the only way I can implement such a library on the C side in the DLL wrapper, since the LabVIEW Variant datatype is NOT documented how to interface to it on the C side of things. It's obviously possible as the NI OPC UA Toolkit shows, but it's for now not an option for me to use since NI does not document how to do that.
The NI OPC UA Toolkit uses LabVIEW Variants in the interface from and to the DLL and then translates them internally to whatever the underlaying OPC UA code they use requires and back. As such what you do in your VI could be done easier with the "Multiple Write (uint32)" and "Multiple Read (Double)", which are simply wrappers that convert the Variants to specific datatypes on the LabVIEW side. That's convenient as it requires only one generic interface in the C code, but not very performant since there are factually several conversions going on that way, OPC UA stream->OPC UA native datatype->LabVIEW Intermediate DSC flatten format->LabVIEW Variant->LabVIEW specific datatype. But my reason not to go this path is not that it is less performant, but because I have no information how to interface to a LabVIEW Variant on the C side of things.
When I'm finished with the current datatype conversion on the C side, I have an OPC UA library that is almost perfectly compatible with the NI OPC UA library, with additional functionality, but without support for LabVIEW Variant datatypes, because I can't implement that without more detailed information from NI themselves. For completeness, I have to say that I haven't tried to get this information from NI yet. I don't know at this point if NI would be willing to share such information in any way and may seek to get such information at a later stage. It wouldn't make the code on the C side much easier though, just different. The only advantage of the use of Variants would be that I also can support other OPC UA datatypes such as structures (LabVIEW clusters). Adding Variant support later on, if I get the necessary information, will however be a fairly easy exercise.
11-25-2024 04:19 AM - edited 11-25-2024 04:20 AM
Just to let you guys know. I have been quite busy lately on this and I'm close to having a pre-release of a client library that can read and write node values, and most probably also support method calls and subscriptions (if I manage to get variant support fully working in my shared library, got the LabVIEW variant to UA Variant working, still haggling a bit with the reverse, which is required for both subscriptions and method calls).
It's still not quite finished and has some potential to crash, but it seems to be close to have a first working version. And I hope that it will be also able to support structures (LabVIEW Clusters) through use of variants, but still need to test how that works on non-built in data types.
11-25-2024 06:51 AM
That is amazing for the community. How did you solve passing variants then?
11-25-2024 07:06 AM - edited 11-25-2024 07:56 AM
@Quiztus2 wrote:
That is amazing for the community. How did you solve passing variants then?
In C code, interfacing to non-public manager exports in LabVIEW. But it is a tricky business and potentially unsafe for future releases of LabVIEW, as witnessed in this thread: https://forums.ni.com/t5/LabVIEW/CallChain-function-extcode-h-is-returning-corrupt-handle/m-p/440778...
This was not for Variants, but involves another non-public LabVIEW manager call that has existed since at least LabVIEW 5 and worked all the time, until it didn't in LabVIEW 2024Q1.
Most exported variant APIs were introduced between 8.2 and 2009 and as far as I could check for the relevant ones, remained present until now. The exported ones are a bit random in terms of supported types and features and often involve also the new LabVIEW 8 32-bit type descriptor that is unfortunately not documented anywhere in any way. It's basically a 32-bit stream implemented as a C++ object interface and that makes it pretty hard to determine anything without resorting to actual disassembly and then things are still almost impossible to follow. The ones I use were mostly sort of inadvertently documented by header files that were distributed with a download to develop your own custom CUDA datatypes. That download seems to have been either pulled entirely or lost in the depths of the NI web content management system.
I did so far my tests on LabVIEW 2009 and 2020 and will also run tests on 2024 before releasing anything. The NI OPC UA Toolkit uses similar functions although they use two functions to convert to and from a variant through a flattened string. But it is not the standard LabVIEW flattened string format but some other private format probably inherited from the DSC/Lookout interface that was internally called Logos and on which also Datasocket and later shared variables are based.
I did entertain a different approach too. Having a complete API in the shared library to access and create open62541 variants and then convert them on the LabVIEW diagram on the fly similar to what the NI OPC UA toolkit does when converting the variants to and from the native datatypes. But I abandoned that as it is pretty much impossible to manage the lifetime of such pointers properly without accessing other non-public features in LabVIEW, so that LabVIEW noobs couldn't utterly and completely corrupt the system with only a little carelessness.
11-25-2024 08:56 AM - edited 11-25-2024 09:02 AM
I really appreciate your investigative work on this. For the sake of NI, I hope they recognize your efforts already done for their product and provide you with some support.
I mean like since improving connectivity to industry standards is the most desired feature in LV right now.