Jump to content

Structures as input parameters


Recommended Posts

You can usually build such structures by using a cluster (in this case it's simple since the structure only has simple data types). To get the value by pointer you set the parameter to "Adapt to Type" and wire the cluster you built into the input. This will cause the DLL node to allocate the memory for the structure and will feed it into the output cluster.

Note that some of the parameters are byte-order sensitive and that to wire in constants you need to know their numeric value (which can be found in the header files). More information about working with DLLs can be found here.

Link to comment

Download File:post-3754-1137613874.zip

You can usually build such structures by using a cluster (in this case it's simple since the structure only has simple data types). To get the value by pointer you set the parameter to "Adapt to Type" and wire the cluster you built into the input. This will cause the DLL node to allocate the memory for the structure and will feed it into the output cluster.

Note that some of the parameters are byte-order sensitive and that to wire in constants you need to know their numeric value (which can be found in the header files). More information about working with DLLs can be found here.

Something similar to the file attached? But it didn't work at all yet :headbang:

Any idea?

Thank you

Link to comment
Download File:post-3754-1137613874.zip

Something similar to the file attached? But it didn't work at all yet :headbang:

Any idea?

Thank you

Basically yes, but I'm not sure what the problem is.

For one thing, you're using I32 for the words, which is wrong. You should use U16 or I16, but I am not sure this would necessarily cause a problem.

The other thing is that I'm not sure whether you can use a LV string to represent a null terminated string inside a struct.

Also, I think you might need to use Handles by Value.

The last thing, and this could be the source of your problem is that your inputs are wrong. You're inputting 1 as the number of the device (if you only have one, that should be 0) and you're wiring 0 as the number of bytes. The number of bytes is probably the trickiest thing to calculate as it seems you will need to know the length of the string.

I suggest you try digging up some more in the page I linked to or, if you're lucky, wait until Rolf will explain what went wrong and whether you will need a wrapper DLL.

Link to comment
Basically yes, but I'm not sure what the problem is.

For one thing, you're using I32 for the words, which is wrong. You should use U16 or I16, but I am not sure this would necessarily cause a problem.

The other thing is that I'm not sure whether you can use a LV string to represent a null terminated string inside a struct.

Also, I think you might need to use Handles by Value.

The last thing, and this could be the source of your problem is that your inputs are wrong. You're inputting 1 as the number of the device (if you only have one, that should be 0) and you're wiring 0 as the number of bytes. The number of bytes is probably the trickiest thing to calculate as it seems you will need to know the length of the string.

I suggest you try digging up some more in the page I linked to or, if you're lucky, wait until Rolf will explain what went wrong and whether you will need a wrapper DLL.

Attached is a doc that explains how to arrange LabVIEW data types to pass them as a struct.

Download File:post-2966-1137640539.doc

Link to comment
Attached is a doc that explains how to arrange LabVIEW data types to pass them as a struct.

That file will probably prove to be useful in the future, but I doubt it will help the original poster, as it still seems the length of the string needs to be known in advance.

Thanks for the file.

Link to comment

Thanks to your very important advices finally I did it. Here is a little example where the use of a structure is done. If you'll run the VI "TestScheda_1.vi" you'll know how many audio devices are available on your system and what's the name of any of them.

So enjoy yourself and make me know if the attached VI works on your system without any problem.

Thank you again the all of you for help :thumbup:

Download File:post-3754-1137774082.vi

Link to comment
Thanks to your very important advices finally I did it. Here is a little example where the use of a structure is done. If you'll run the VI "TestScheda_1.vi" you'll know how many audio devices are available on your system and what's the name of any of them.

So enjoy yourself and make me know if the attached VI works on your system without any problem.

Thank you again the all of you for help :thumbup:

You do not want to disable unreadable characters but instead go in a while loop and abort at the first occurrence of a NULL character and then resize the byte array to this length - 1 and then put it through a Byte Array To String node. The string in there is a zero terminated string, as all C strings are so and once you encounter \00 it is over and the rest is only garbage that happened to be in memory before the function filled in the information.

Rolf Kalbermatter

Link to comment

That's nice, but you still need to know the length of the string. You input 34 as default, but this is not enough on my system and some point inputting an arbitrary larger number could return invalid results or crash LV. If there is a function which returns the names of all devices in advance you might want to use that and add the rest of the bytes to the length of the string.

Link to comment
  • 2 weeks later...
That's nice, but you still need to know the length of the string. You input 34 as default, but this is not enough on my system and some point inputting an arbitrary larger number could return invalid results or crash LV. If there is a function which returns the names of all devices in advance you might want to use that and add the rest of the bytes to the length of the string.

In fact 34 is to long. The MS SDK uses here a fixed length of 32 chars for this. There is therefore no way to return a string longer than 31 characters through this function. Looking at the Vi I do see a few more problems.

First the device number is supposed to be a value between "0" and "number of devices - 1". Therefore the -1 node in the wire from the iteration terminal to the CLN seems wrong. Ok, it seems that MIDI_MAPPER (= -1) is also a valid value for this function so the whole idea about increasing the number of devices by one and decreasing the index inside the function by one to get also the MIDI_MAPPER device is a valid idea, although I would have made a comment about this in the diagram just for the future user that sees this code.

Second the string embedded in the structure should only be 32 characters long (and not 35 as it is now) which is the value of MAXPNAMELEN. This is no problem here only, because the function does not try to interpret the values after the string. If it would it would read wrong data since everything is shifted by three bytes.

Last but not least is the third parameter to the CLN wrong. This is the length of the structure in bytes and is definitely not 38 bytes but more something like 52. 38 is in fact not even long enough for the function to return the entire string, as the structure up to and including the entire string placeholder is already 40 bytes long.

Rolf Kalbermatter

Link to comment
In fact 34 is to long. The MS SDK uses here a fixed length of 32 chars for this.

...

This is the length of the structure in bytes and is definitely not 38 bytes but more something like 52.

Yes, that's what I meant. I seem to have forgot that the size asked was for was the size of the structure and not the string.

I learned something here. I didn't realize the size allocated for the string was set. Is this a standard thing in windows API functions where you're expected to input a size? I would expect it to be, but I never noticed before a place where you have an additional piece of data which can be found in the header file. Then again, I never looked very hard into this.

You have to wonder what's the point of using null terminated strings if you have a predefined size. Is this something required for C compatibilty or is just to make it easier for C programmers?

Link to comment
I learned something here. I didn't realize the size allocated for the string was set. Is this a standard thing in windows API functions where you're expected to input a size? I would expect it to be, but I never noticed before a place where you have an additional piece of data which can be found in the header file. Then again, I never looked very hard into this.

You have to wonder what's the point of using null terminated strings if you have a predefined size. Is this something required for C compatibilty or is just to make it easier for C programmers?

It is quite common in WinAPI functions to specify the size of structure parameters passed to a function. Most often this is done in the first member variable of the structure itself but as can be seen there are exceptions such as this were you pass it as a spearate parameter.

Why would you do that??? Simple! For version compatibility. Newer implementations of such a function can add extra elements at the end of the structure. If an application that was compiled with an earlier header file calls this function, the function can check the size, possibly recognize the version this application expects but most importantly make sure it only returns the information the structure can hold, avoiding writing past the end of the memory area reserved by the caller for the structure.

The string in the structure is NOT fixed size. Only the area reserved for the string in the cluster is fixed size. This is common practice to avoid having to reference any parameters after a string at variable offsets, depending on the size of the embedded strings. In fact it is the only way to declare a structure at compile time. If you use variable sized strings in a structure you can't declare that structure at compile time but instead need to parse it dynamically at runtime.

The function will fill in a NULL terminated string in that area up to the reserved length minus the 0 termination character. So the NULL termination character still is needed for the caller to find how long the actual string is. This is the point of my first post. You do not want to return all 32 characters that are reserved in the structure, but instead go through those 32 characters and stop at the first occurrence of a NULL character, since that is the end of the string. It is also a good practice to not assume that the string will be NULL terminated so you will go in a while loop and stop looping when a NULL character is found OR when the length of the array has been consumed. Not strictly necessary but a good idea and this is really called defensive programming.

Rolf Kalbermatter

Link to comment
It is quite common in WinAPI functions to specify the size of structure parameters passed to a function.

I have noticed it is common to set a size, just not that windows already gives you that size. My question was whether you get the size every time or whether sometimes you have to figure out the size on your own.

If an application that was compiled with an earlier header file calls this function, the function can check the size, possibly recognize the version this application expects but most importantly make sure it only returns the information the structure can hold, avoiding writing past the end of the memory area reserved by the caller for the structure.

So why can't the size be specified in advance in the header file? Why do I need to tell the function what the size will be? Is it because several header files can be used for different parts of the function call? Can header files from different versions be used at the same time?

It is also a good practice to not assume that the string will be NULL terminated so you will go in a while loop and stop looping when a NULL character is found OR when the length of the array has been consumed. Not strictly necessary but a good idea and this is really called defensive programming.

That I know. I was actually just explaining that a couple of days ago to a friend of mine who's learning software engineering (learning C++, the poor guy :blink: , but he will probably know how to properly call windows API functions long before I have enough time to properly do this).

Link to comment
I have noticed it is common to set a size, just not that windows already gives you that size. My question was whether you get the size every time or whether sometimes you have to figure out the size on your own.

So why can't the size be specified in advance in the header file? Why do I need to tell the function what the size will be? Is it because several header files can be used for different parts of the function call? Can header files from different versions be used at the same time?

You lost me. Where did you see that you get the size from somewhere? What are you trying to say?

Rolf Kalbermatter

Link to comment
You lost me. Where did you see that you get the size from somewhere? What are you trying to say?

Rolf Kalbermatter

Correct me if anything is wrong - to get the size of the structure, I have to go to the specified header file (mmsystem.h) and find the define statement for MAXPNAMELEN (that's what I mean by "get" - it is predefined). Then I have to add the size of each parameter to that and that will give me the size of the structure, which I can now feed into the function.

So, why can't the compiler go to the header file (assuming I use an include statement) and find out the size itself and add to it the size of the other parameters? Why do I need to this manually?

All this probably shows you that I don't have any real C experience. I have briefly learned both basic and C on my own, but never enough to do anything with it.

Link to comment
Correct me if anything is wrong - to get the size of the structure, I have to go to the specified header file (mmsystem.h) and find the define statement for MAXPNAMELEN (that's what I mean by "get" - it is predefined). Then I have to add the size of each parameter to that and that will give me the size of the structure, which I can now feed into the function.

So, why can't the compiler go to the header file (assuming I use an include statement) and find out the size itself and add to it the size of the other parameters? Why do I need to this manually?

All this probably shows you that I don't have any real C experience. I have briefly learned both basic and C on my own, but never enough to do anything with it.

A C compiler does just that. You use the sizeof() keyword for this and that will calculate the compile time size of any datatype including structures and use that value in the compiled code. LabVIEW obviously does not have C parsing capabilities so can't do anything for you with that header file.

Rolf Kalbermatter

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.