LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to pass structure into dll?


JHugh wrote:

I also assume that s6_addr = 0000000000000001 since we only have 16 char available. I would enter it as an inner cluster in ASCII format i.e. 0 = (uInt8) 48 and 1 = (uInt8) 49.  Is this assumption correct or am I wrong to assume uInt8 is in ASCII?

The array of 16 U8 values allocates enough space to store an IPv6 address. An IPv6 address is 16 bytes, unlike an IPv4 address which is only 4 bytes. This is a binary value, not ASCII.

 

I encourage you to continue working on this project after you take a class in C programming. Right now you're making completely incorrect assumptions, then asking this forum to correct them. You're asking a LabVIEW forum to teach you C; your questions no longer have anything to with LabVIEW. You might eventually get working code out of this but you won't have an understanding of why it works and you'll have a limited ability to debug it when it doesn't work.

 

If possible, set up a linux system on a PC that you use regularly (you can do this as a virtual machine). Write some simple C programs. Before diving into IPv6, write some IPv4 code (as a standalone C application) to get an understanding of the socket functions. Once you have that working, conversion to IPv6 should be fairly straightforward. After that, you'll be able to build the LabVIEW code with high confidence that you understand how it works, and if you run into LabVIEW-specific issues at that point, come back here and post your actual code along with a detailed description of the problem.

0 Kudos
Message 11 of 13
(515 Views)

I have thought about this a bit more. My advice is similar than what nathan has told you. Learn C programming. But then write a shared library in C to translate between a LabVIEW friendlier API and the system platform API.

 

You may feel that you have no time to first learn properly C and then writing a shared library in C and then a LabVIEW interface for your shared library. That could be true, but reality is, that if you don't know how to write such an interface shared library in C you have very little chance to do this all in LabVIEW instead. In addition to everything you need to know to be able to write that shared library in C you also need to know how a C compiler in general and your GCC compiler for the NI Linux Realtime platform places and aligns data in memory, in order to play C compiler on the LabVIEW diagram yourself! That is more complicated than "only" knowing how to write C code.

 

I have written such a LabVIEW library in the past, with all the real work done in a C coded shared library, and although it supports among IPv4 and IPv6, also SSL and therefore is a bit more complex, it took me maybe 1000 man hours in the end to do it. And that was just for Windows, with the provisions to also make it work for Linux and Mac OSX but the non Windows platforms never were fully tested and finished because of lack of time. To add support for the NI Linux system would be probably not a lot of extra time in programming but getting it all to compile and then testing and debugging it, would be another 50 to 100 hours.

 

The idea to write this entire library entirely in LabVIEW seems in the first instance tempting as you can supposedly avoid a few hassles with getting the correct C toolchain installed and properly configured but to me it looks more like a supporting nightmare. The fact that 64 bit and 32 bit LabVIEW on Windows use different memory alignment options is only one of those extra troubles that would make it often necessary to write two different Call Library Nodes depending on the bitness of the LabVIEW platform. And the fact that all these platforms use a Berkeley Socket derived network socket interface doesn't mean that a lot of the direct interface code would not need to be implemented in a conditional compile structure to support other platforms.

 

The more harmless difference between platforms in that respect are the AF_ constants and similar that have different numeric values on different platforms. If you write this in C you simply type AF_INET6 and the C compiler will automatically insert the correct value during compilation based on the defines in the system headers. Same about variations in datatypes for the parameters of function calls. You don't have to go and painstakingly check every single parameter and other datatype in the headers (which can be already a challenge to find the right header for them) but mostly let the compiler worry about that. If you happen to pass an incompatible data type to a function you get a quick and swift compiler error and if it is compatible the C compiler will generate the according conversion automatically if that should be necessary. In the LabVIEW Call Library Node if you happen to use a double where the function expects a single, there is no compiler who can warn you about that based on the right header files, instead you get a crash or other weird behavior at runtime.

 

As to filling in the 16 bytes of the sin6_addr, they are full binary bytes, you don't do that as a string. This address supports 2^(16*8) addresses and you really don't want to be bothered with having to figure out the bit values for that.

The IPv6 address syntax for the binary address is complicated enough that implementing a parser for it alone, that would work correctly in all possible corner cases, is an entire engineering project in itself. Instead all modern socket libraries come with facilities that allow you to parse a string in binary or domain name address syntax into the correct 16 byte binary byte stream. Look for getaddrinfo() and its counterpart getnameinfo() to see how this can be done and be in awe that you will have to deal with even more extended structure type parameters than before!

 

struct addrinfo is an interesting beast which can and often is a linked list of struct addrinfo pointers and at this point trying to do this on the LabVIEW diagram instead of in a C shared library really gets annoying. Also every addrinfo struct parameter returned by getaddrinfo() needs to be deallocated by freeaddrinfo(), something most LabVIEW programmers would likely forget.

Rolf Kalbermatter
My Blog
0 Kudos
Message 12 of 13
(482 Views)

I have not looked into your specific issues, but the very first question about passing a structure into a dll is "Do I actually need to access the structure internals in LabVIEW, or can I just pass a pointer?"   If you get a pointer to a structure from one dll call, and pass it to another dll call, then you only need to get/pass a single "pointer-sized integer" in LabVIEW.  Only if you need to create or modify a C structure in LabVIEW is there any difficulty.  

 

On my very first wrap-a-dll task I did not understand this, and wasted lots of time matching a LabVIEW cluster to large complex C structure, when I could have just passed a single integer.

 

 

0 Kudos
Message 13 of 13
(470 Views)