LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Import C++ function with array argument with the Shared Library Wizard

Solved!
Go to solution

I am using the Import Shared Library Wizard to import functions in a C++ DLL to my VI in LabVIEW.  Some of the arguments to these functions are arrays.  Unfortunately, the Wizard doesn't recognise these as arrays and instead treats them as single values.

 

For example, one function has a

bool*

to indicate an array of Booleans, but the Wizard interprets this as a single Boolean value:

 

ed_graham_0-1701961377264.png

 

I also tried declaring the function like this in my header (.h) file:

 

extern "C" MSTKINTERFACEDLL_API bool configEnableChannels( hMstkHandle uiConnectionHandle, bool boEnabledChannels[MAX_MSTK_CHANNELS_HANDLED] );

 

However, that didn't make any difference.

 

I see from the documentation that one-dimensional arrays ought to be handled by the Wizard:

 

For most DLLs, using the Import Shared Library Wizard will generate code that will handle simple datatypes like integers, floats, one-dimensional arrays and strings.

 

However, the web page showing data types supported by the Wizard doesn't mention arrays at all, so perhaps they're not supported after all.

 

How can I present functions with array-type parameters so that the Wizard will correctly identify their signatures?

0 Kudos
Message 1 of 10
(2,795 Views)

Thanks Alex.  It's not obvious how they help me, however, as neither of them refers to the Shared Library Import Wizard.

0 Kudos
Message 3 of 10
(2,767 Views)
Solution
Accepted by topic author ed_graham

The Shared Library Wizard unfortunately doesn't work properly for many types. It tries to parse interfaces from the headers, and it depends - sometimes it works (then can save huge amount of work), sometimes not, then you have to adjust calls in LabVIEW manually.

 

For the bool - if you using bool from <stdbool.h>, then LabVIEW's Shared Library Wizard will parse it as char, then you have to convert your array to the according representation:

Screenshot 2023-12-07 17.00.59.png

MSDN tells me that In Visual C++, the Standard C++ header files contained a typedef that equated bool with int, so you may need to pass it as [I32] type instead, that is.

Message 4 of 10
(2,745 Views)

Thanks Andrey - I wondered if that might be the case.  I will add an equivalent function to the DLL that doesn't use arrays!

0 Kudos
Message 5 of 10
(2,715 Views)

@Andrey_Dmitriev wrote:

 

MSDN tells me that In Visual C++, the Standard C++ header files contained a typedef that equated bool with int, so you may need to pass it as [I32] type instead, that is.


bool is originally a C++ datatype only but was added to the C99 standard too. And in true C manner, the standard says absolutely nothing about the exact size of this datatype. It only states that it needs to be able to store the two states in some way. How the type is implemented is entirely left to the compiler builder.

 

Traditionally most C++ compilers choose to use a byte for the bool in an effort to balance memory usage with efficient access to a bool value. Most CPUs are not able to address a single bit efficiently but usually can address 1 byte fairly well. A C/C++ compiler builder is however completely in their right to choose for instance a 32-bit value or even a 64-bit value for this, if the hardware in question has a better performance for that datatype than single byte accesses, for instance.

 

Visual C only used a 32-bit value for bool up to version 4.2 and also only for C++ compilation. Visual C 5.0 which also only allowed for C++ bool's, used a single byte and ever since did so.

Visual C (without ++) only included a stdbool.h (and stdint.h) definition file since about version 2008 and could not deal with bool in standard C code files out of its own in older versions.

But you might also be mixing that up with BOOL, which is not a compiler datatype but a Windows API datatype and is indeed defined as a 32-bit value.

Rolf Kalbermatter
My Blog
Message 6 of 10
(2,657 Views)

@ed_graham wrote:

Thanks Alex.  It's not obvious how they help me, however, as neither of them refers to the Shared Library Import Wizard.


from my experience, when using the shared library import wizard and arrays are involved, it is likely to fail.

 

but in general, it is possible, as shown in

 

 https://forums.ni.com/t5/Developer-Center-Resources/Dereferencing-Pointers-from-C-C-DLLs-in-LabVIEW/...

- Special Case: Dereferencing Arrays

- Special Case: Dereferencing 2d Arrays

 

the snippets provided in this article helped me when I had to use a .dll - that was provided by a third party- in labview.

in my case, the shared libray wizard also wasn't able to import 2d array stuff properly, but in general it is still possible to interchange 2d array data from within labview via the call library node.

 

 

 

Message 7 of 10
(2,576 Views)

I've stated many times that the Shared Library Import Wizard is despite its name not a magician. But that would be required to be able to properly import code purely based on a C header file.

 

C syntax is notoriously unprecise in defining the meaning of a lot of things. A lot of it has to be determined by the programmer at the moment he is using any specific library based on (sometimes) available documentation. Without documentation it may also be possible to use existing sample code that shows the use of the API and if that is not available, there is only trial and error left, together with common sense based on for instance naming conventions of variable names and similar. Everything in this paragraph is absolutely impossible to be done by any kind of wizard, even with algorithmic intelligence.

 

I have often felt that the Import Library Wizard is in fact a bad idea since it gives lots of people the idea that they can interface to shared libraries without knowing what they are doing. If you can't correctly configure the Call Library Node yourself manually, using the Import Library Wizard simply will more often than not give you a solution that is simply wrong. The worst thing on that is that a wrong configuration of the Call Library Node does not have to crash your program. If it does you are lucky, instead it could simply corrupt your memory and cause your application to crash much much later on completely unrelated code execution, or even more interestingly corrupt your precious data that you use to calculate the proper operation of your multi million dollar rocket.

 

Please, anyone planning on using the Import Library Wizard should remember that it can NOT import any non trivial library interface reliably. It's not because the Import Library Wizard is a badly implemented piece of software, but simply because the C syntax does not provide enough information to reliably do that job. The C syntax does not make any difference between a scalar passed by reference and an array of things, it has no clear concept of typed pointers beyond basic scalar datatypes, can't describe memory requirements for any kind of buffer that an array is, nor the relationship between two or more parameters with one describing the size of the other in any of a few dozen variants.

 

The Import Library Wizard is at best a tool to create the template for importing a shared library. If you don't spend a lot of time in reviewing every single of those VIs for proper implementation of buffer sizes, and also simplifying the interface to match LabVIEW conventions, you basically simply created a huge useless crash site.

 

 

 

int function(int32_t *buffer, size_t *length);

 

Take this simple prototype. How should the wizard know that buffer is probably an array of length elements? Both parameters are simply reference variables. We humans can infer that from the naming of the variables, but it could just as well be called:

 

int function(int32_t *b, size_t *l);

 

Hmm, much less guessable. And the problem is a software program can't even start to guess.

Also even if it would get it right by assuming that buffer must be probably an array there are still several bears here. Why is the length character passed by reference? It could be that the function expects on entry the length of the available buffer in there and then will update the value with how many elements it actually filled in. That would be smart, but you can't imagine how many libraries are out there that look like this but do completely different things.

 

If you are very lucky there is a documentation for your function that is a little more elaborate than this:

 

int function(int32_t *buffer, size_t *length);

buffer: the buffer for the data // Doh really, who had not guessed that
length: the length of the buffer // I would never have imagined that!!!

Returns:
some error code // interesting, could you be please a bit more elaborate about this????????

 

Basically it would be interesting to know how big the buffer should be on entry to the function, and a bit more information about how the length is meant. It could be the number of array elements, but it could just as well be the number of bytes (yes that is not fabricated but happened in a recent API I wanted to import).

 

If this LabVIEW VI for this function is smartly written, the calling interface in LabVIEW should simply allocate an array of the necessary size on the diagram, pass the length of that array in the second parameter and then use the returned length to resize the array to the length the function actually filled in. The according VI only has an array indicator output and maybe a length control input, aside from the obligatory error cluster inputs and outputs.

 

The LabVIEW user of that function should not have to be concerned about how the array needs to be allocated nor resized, that is a feature/handicap of the C API and does not belong in the exposed interface to the LabVIEW user! Most of this can however not be done by any computer wizard no matter how much Bard and ChatGPT you throw at it. It is manual programming work.

 

So yes, use the Import Library Wizard if you must but after it has run, don't expect it to have created correct code. Treat the result as a collection of VIs that you absolutely MUST review, revise and sometimes substantially rewrite piece for piece in order to be a usable software result. The Import Library Wizard can be good to get you started with templates for the various functions the shared library exports, but you have to carefully check every such VI to do exactly what the function requires and you need to be able to understand what each function requires to great detail or you simply create crashing software.

Rolf Kalbermatter
My Blog
Message 8 of 10
(2,549 Views)

I hear you, Rolf!

0 Kudos
Message 9 of 10
(2,311 Views)

And I just found out that it took Microsoft to release Visual Studio 2013 before they (partly) supported C99. Not exactly sure when they had stdint.h and stdbool.h in the headers though, it could have been earlier, but definitely not in VS 2005.

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 10
(2,305 Views)