04-09-2018 03:50 PM
I have developed a C library which runs on Windows, Linux, and NI ETS. I am in the process of developing a LabVIEW wrapper for the said library. Is there any way to configure the packing in the C library to be able to use one consistent structure in LabVIEW across all the operating systems and bit-sizes without modifying the C library?
I have read a KB on LabVIEW memory and how it is different on each operating system. Then found another KB which speaks about lining up clusters with structures. It says that the structure packing can be changed so the structure is aligned with the LabVIEW cluster.
I suppose I can construct some #ifdefs which will match the packing with the LabVIEW memory layout for each operating system. I prefer not to change my library to facilitate a wrapper as there is good chance I will wrapper the library in C# and perhaps other languages. Is there something I can do from the LabVIEW side? Is the best approach to create a case structure in LabVIEW and select the best structure to use for the OS?
04-09-2018 05:28 PM - edited 04-09-2018 05:36 PM
Use the two include files from the cintools directory around and structure type declaration that you use in the exported functions that you want to call through the Call Library Nodes as follows:
#include "platdefines.h"
......
#include "lv_prolog.h" typedef struct { int32.t elm1; float64 elm2; ........ } whatever_struct; #include "lv_epilog.h"
lv_prolog.h sets up the packing according to the LabVIEW rules for the current platform you are compiling the shared library for.
lv_epilog.h resets the packing back to whatever the compiler used before the lv_prolog.h inclusion.
The alignments used by LabVIEW are different on different platforms. 32-bit x86 platforms tend to use byte packing, 64-bit x64 platforms use the default alignment, which is usually 8 byte. The PPC platform for some of the cRIOs has its own settings.
On MacOSX LabVIEW uses whatever is the default alignment for the compiler independent if it is 32 or 64 bit. Same on Linux but the standard GCC compiler doesn't know a consistent configuration to set the alignment to the natural default. Generally for all but MacOSX and Windows 32-bit compilation, changing in your project the alignment to anything but the default alignment will surely mess up your alignment of the structures for interfacing with LabVIEW.
04-10-2018 04:35 AM
If you are the developer if this c dll then I suggest you provide functions to write/read parts of your structure, then only handle the structure in LabVIEW as an integer pointer passed between these functions. Then details about packing never come up.
04-10-2018 05:19 AM - edited 04-10-2018 05:19 AM
@schddc wrote:
Is the best approach to create a case structure in LabVIEW and select the best structure to use for the OS?
Not a case structure, but a conditional disabled structure. Things like this is the purpose of the structure.
04-10-2018 05:49 AM
@drjdpowell wrote:
If you are the developer if this c dll then I suggest you provide functions to write/read parts of your structure, then only handle the structure in LabVIEW as an integer pointer passed between these functions. Then details about packing never come up.
I want to add that I think that providing functions (that act on a pointer to a structure) is a better way to allow wrapping in any language. It’s an object-like encapsulation; a simple public API. I don’t write C dlls but I’ve wrapped a few, and the best ones (such as SQLite, that has been wrapped in many languages) don't expose raw structures.
04-10-2018 07:39 AM - edited 04-10-2018 07:42 AM
@drjdpowell wrote:
@drjdpowellI want to add that I think that providing functions (that act on a pointer to a structure) is a better way to allow wrapping in any language. It’s an object-like encapsulation; a simple public API. I don’t write C dlls but I’ve wrapped a few, and the best ones (such as SQLite, that has been wrapped in many languages) don't expose raw structures.
For DLLs (shared libraries) that you ever might want to interface to other environments too, this is definitely true! Python would come to mind as a possible environment, but Matlab just as much. Their interfacing to external libraries is similar with a scripting like approach that defines the parameter list of functions. While they allow to also describe structure datatypes in that way, it is cumbersome, error prone and generally quite a hassle to get right, and alignment issues between different platforms (yes Python can run on just about anything that has a C compiler available), would make the according definitions pretty convoluted if you intend to support more than one platform.
For a shared library that is only intended to be used by LabVIEW I would personally not hesitate to use the two earlier mentioned include files.
04-10-2018 08:08 AM
@rolfk wrote:
@drjdpowellFor DLLs (shared libraries) that you ever might want to interface to other environments too, this is definitely true!
That is what the OP is trying to do; make a common dll callable from many environments without modification. In my SQLite wrap, I used the pre-compiled dll from the SQLite website, which is made by developers that may never have even heard of LabVIEW, and it worked fine.
04-10-2018 08:25 AM - edited 04-10-2018 08:28 AM
@drjdpowell wrote:
@rolfk wrote:
@drjdpowellFor DLLs (shared libraries) that you ever might want to interface to other environments too, this is definitely true!
That is what the OP is trying to do; make a common dll callable from many environments without modification. In my SQLite wrap, I used the pre-compiled dll from the SQLite website, which is made by developers that may never have even heard of LabVIEW, and it worked fine.
Correct. I'm trying to make a common dll without custom modifications specifically for LabVIEW. I already have a wrapper for C# with works if I have to recompile the dll with new packing then it would require me to change the C# wrapper which is unpleasant.
I'm really trying to understand the best way to handle this internal to my LabVIEW VIs. Since I will be using and supporting LabVIEW on at least Win 32, Win 64, and NI ETS I have to worry about the different packings used on the different systems.
Currently, I have multiple variants of my structure with different padding and one variant of the structure with no padding. I use a conditional disable structure (not case structure thanks wiebe@CARYA) to select the appropriate structure to use for the CLN. I then map the OS padded structure to the no padding structure. I was hoping there was a better way to do this.
04-10-2018 08:27 AM
@drjdpowell wrote:
@rolfkThat is what the OP is trying to do; make a common dll callable from many environments without modification. In my SQLite wrap, I used the pre-compiled dll from the SQLite website, which is made by developers that may never have even heard of LabVIEW, and it worked fine.
I think it is debatable if he really wanted to call this DLL from other environments than LabVIEW. Especially the mentioning of NI Pharlap ETS would indicate that it is mainly a LabVIEW RIO solution, (Linux probably too for the Linux based RIO devices), and then of course LabVIEW for Windows for the development environment (the only platform you can really develop NI RIO applications on).
04-10-2018 08:30 AM
@drjdpowell wrote:
@rolfk wrote:
@drjdpowellFor DLLs (shared libraries) that you ever might want to interface to other environments too, this is definitely true!
That is what the OP is trying to do; make a common dll callable from many environments without modification. In my SQLite wrap, I used the pre-compiled dll from the SQLite website, which is made by developers that may never have even heard of LabVIEW, and it worked fine.
Correct. I'm trying to make a common dll without custom modifications specifically for LabVIEW. I already have a wrapper for C# with works if I have to recompile the dll with new packing then it would require me to change the C# wrapper which is unpleasant.
The tip about including the labVIEW header files was great but I don't think it's what I'm looking for. I have seen them used before but didn't understand what they did. So it was helpful to get an explanation of them. Now I have them in my toolbelt for the future.
I'm really trying to understand the best way to handle this internal to my LabVIEW VIs. Since I will be using and supporting LabVIEW on at least Win 32, Win 64, and NI ETS I have to worry about the different packings used on the different systems.
Currently, I have multiple variants of my structure with different padding and one variant of the structure with no padding. I use a conditional disable structure (not case structure thanks wiebe@CARYA) to select the appropriate structure to use for the CLN. I then map the OS padded structure to the no padding structure. I was hoping there was a better way to do this.