Jump to content

Recommended Posts

Thanks to the nice work of drjdpowell I was able to easily connect & work with PostgreSQL. Did have to use the 32bit included dll's though.

Now when I try to install & run it on a Win10 IoT machine the dll's are not found and throwing errors. Sorry no screenshot at the moment.

The 64bit of PostgreSQL is installed on both machines & works.

The exe of course works just fine on the dev machine.

Does anyone have any ideas? I'm at a loss at the moment & need to get this running.

Thanks.

Share this post


Link to post
Share on other sites

I'll have a look when I get a chance.  You might just need to install 32bit postgres, just to get the pq dll from it. 

Share this post


Link to post
Share on other sites

If this is an EXE, see if libpq.dll and other dlls are included with the EXE, in its "data" folder.  This should happen automatically (because the dlls are part of the PQ class), but I've seen this fail before.  If they aren't there try using "Always Include" to include them.  The data folder should look like this:

880985272_2019-07-0310_32_46-TestPQProperties.png.5c045053bf59532f8f04a8773dd653a1.png

Share this post


Link to post
Share on other sites

Correct, the above is exactly the same for the build & works from different directories on the dev machine. It's on the deployed machine it gives errors.

In the Build properties for the exe I've tried to set the destination to a specific path but it didn't help. Perhaps I missed something?

image.png.a02c1101d4a8e779c13c11bd44cb3cbc.png

Share this post


Link to post
Share on other sites

If those DLLs are there then my only idea is that perhaps there is an additional dll that is needed, one installed on your Dev machine but missing on the deployed machine.  What is the exact error message?

Share this post


Link to post
Share on other sites

Try your exe on a regular Windows 10 computer that does NOT have Postgres installed.  This is to tell if it is a missing dll in the build, or something about Windows IoT that is the problem.

Share this post


Link to post
Share on other sites

On a regular Win10 box the exe loads the dll's just fine & then times out as expected without Postgresql installed. So it's looking a lot like a Win IoT issue...

My understanding is that you wrapped 32 bit dll's with a CIN.

Looking at does-windows-iot-support-my-dll

the answer was:

Windows IoT required DLL to be as follows:

  • Compiled using the ARM target
  • Needs to target .NET Core

Those restrictions strictly apply when using UWA you may be able to get away by using a console app but it is not that simple on IoT as everything is sandboxed.

Otherwise the other way to use the DLL on the Pi is to run a nix OS like Raspbian, install the latest MONO and then you can embed DLL's into your projects and it should just run, even if targeted for x86 - Thanks to all the clever stuff mono does.

Edited by FixedWire
typo

Share this post


Link to post
Share on other sites

Ah, so you need to get DLLs compiled for ARM.  I think I just got those DLLs from the postgres install.  If you have postgres on the ARM, look for those DLLs and replace the current versions with them.

Share this post


Link to post
Share on other sites

If Postgres is already running on the Win 10 IoT box, I should be able to link the CINs to the same installation C:\Program Files\PostgreSQL\11\bin. Theoretically.

LabVIEW 64bit hung up when linked to these installed dll's. Hence using the 32 bit dll's supplied & going that route in the first place. It just worked. Note that there also some changes such as libint.dll likely replaced by the libintl-9.dll in the \11\bin directory.

Win 10 IoT Enterprise should be able to run regular programs where as the Core version is limited to UWP apps (understanding this requires ARM compiled code). what-s-difference-between-windows-10-iot-versions

I think Win IoT is mulching things somehow where regular Win 10 accepts the dll's.

Looks like the best approach for right now is to remotely get into the database via the localhost/IP address and run things on a laptop. Your help's been very appreciated!

Share this post


Link to post
Share on other sites

Windows IoT is not a normal Windows installation at all, except the Windows IoT Enterprise version. The others are really just embededded kernels without any real Win32 subsystem. Accordingly many standard Windows DLLs like kernel32.dll, user32.dll and many more are not present there. It is basically a Windows installation with a much smaller embedded kernel that only supports Universal apps from the app store.

Accordingly a normal LabVIEW build application that you created on your dev machine should NOT even be able to be started as they are build for x86 and not ARM and require a fully functioning Win32 subsystem. How do you target your IoT system?

Share this post


Link to post
Share on other sites

Yes, correct Rolf. The target was the enterprise version & that's why it ran in the first place.

Interestingly enough installing the exe on 3 other machines under Win10 resulted in the 2 working & the 3rd not finding the dll just like the Win10 IoT. With a new build it suddenly didn't find the dll on one that did work. With not having time to debug I created an installation and the program worked since even with new builds. On regular Win10 there shouldn't have been an issue...
At this point I'll try and link the latest 64bit Postgres dll's & try that.

Share this post


Link to post
Share on other sites

Well in that case the remark about the DLLs having to be compiled for ARM was really off. That is for Windows IoT installations on targets like the RPi and similar boards which all have an ARM CPU (and accordingly can't run Windows IoT Enterprise either which is a pure x86/x64 install).

It all depends on which C compiler they used to create those DLLs. Until Visual C 2015 or so each Visual C version come with it's own specific C runtime library that had to be installed on every target on which you wanted to run an executable or DLL created with it. While many parts of Windows are compiled with Visual C too and therefore cause the Windows installation to come with the needed C runtime support already installed this can and will vary depending on the Windows version and the amount of extra tools and utilities that you install. Also any extra custom application you install such as LabVIEW also comes of course with the necessary C runtime support that gets installed if not already present on the system, but depending on all this a particular C runtime version may or may not be present on any particular system.

Basically you should never copy DLLs to a target system but install them with the proper installer for them which hopefully takes care about installing the correct C runtime support too.

Share this post


Link to post
Share on other sites

Since there's still an issue with 32 working (but not on some machines) & the 64 bit hanging when trying to relink the dll to the installed PQ libraries, I tried to create the CIN wrappers automagically. The process gets stuck and becomes beyond my current knowledge. Don't know how you did it but kudos to you Mr. Powell! I'm sure you wrestled with this a bit. 😬

 

Looks like multiple .h files need to be referenced. libpq.dll needs the libpq-fe.h which in turn needs the stdio.h, postgres_ext.h & pg_config_ext.h according to: https://doxygen.postgresql.org/libpq-fe_8h.html

Just selecting a few basic options like open/close was not successful & returned: "The library specified for this node cannot be found or cannot be loaded."

Do you remember how you did it?

 

image.png.1a004dbf5176688e1eac268ce7c8677e.png

Share this post


Link to post
Share on other sites

This has nothing to do with a CIN whatsover. CINs were a legacy technology in LabVIEW 3 and 4 before LabVIEW learned to interface to shared libraries (*.dll on Windows and *.so on Unix). What you are doing is not a wrapper either in the sense as it is usually used by me and others who are regularly dealing with this. A wrapper is another shared library written in C/C++ that interfaces to a certain API and translates it into a more LabVIEW friendly shared library interface that can be more easily interfaced with the Call Library Node.

You are trying to create a VI interface library to your shared library. And that is always a tricky business. For one the Call Library Node can't interface to every C feature out there. C++ object interfaces, callback pointers and also complex structures with embedded pointers are all things that can't be done with the Call Library Node (or in the case of complex structures with embedded pointers only with a lot of pain and by handcoding in LabVIEW what a C compiler would normally do mostly automatically).

The import library wizard you are trying to use for this is an amazing piece of software but despite its name NOT a magician. And extracting all the necessary information from a header to safely interface LabVIEW to a C shared library would be a truely magical feat, since the C syntax does not cover all the necessary details about buffer management and such things. This is only documented (if you are lucky) in the prosa library documentation that comes with your shared library. If you are unlucky you have to figure it out by guessing from naming conventions of variable names and lots of trial and error (meaning: crashing, restarting, editing, saving, crashing, goto begin). This is true for using a shared library in C just as much as in any other language including LabVIEW.

So even if the import library wizard can import all your functions you really have to go through each generated VI and manually check that the generated code is actually correct. Also the generated code is in an attempt to be rather safe than sorry often unneccessarily inefficiently programmed, which is another thing you should be changing. Of course this all requires that you know exactly how the shared library should be interfaced and if you really do that you end up very quickly with the constation that creating all those interface VIs from scratch by hand is not only about as fast as going through the import library wizard and then painstakingly check each of the VIs by hand, but also creates more efficient interface VIs with something more meaningful than the ugly standard light blue import library wizard icons and totally unpractical connector panes.

The import library wizard for instance can't know that in a function like:

int32_t MyAwesomeBufferReader(int32_t *buf, int32_t bufSize, int32_t *bufRead)

the second parameter is the size of the passed in buffer and the third is the size of how many data was actually filled in the buffer. It doesn't even know that the first is not just a pointer to a single int value but rather a pointer to an array. The C syntax does not distinguish between a pointer to a scalar and a pointer to an array, except that it allows to usually write 

int32_t MyAwesomeBufferReader(int32_t buf[], int32_t bufSize, int32_t *bufRead)

to show that the first parameter is actually an array, but this is not used by many programmers despite its increased readability (probably because some ancient C compilers didn't know about this syntax with an incomplete array size and some libraries are still written to compile even on computers that you can only see in musea anymore).

The first variant will likely default to a VI with an int32 value "bufSize" as input and two int32 value "buf" and "bufRead" as output and if you select the option to treat return values as error it will enter the return value into the error cluster as an error if it is not 0. It will also corrupt memory (and likely crash at some point) whenever being called with a bufSize value greater than 1!

The proper VI (just going from the somewhat arbitrary naming of the parameters) has however an int32 "number of samples to read" as input that says how much data should be read, and an int32 array output. Before calling the shared library function the interface VI should allocate an array of "number of samples to read" in length and on return of the function should use the "bufRead" value to resize the array to the actually returned data and then pass it back through the array output of the connector pane . The interface VI should hide all the buffer management details from any caller of the VI as otherwise you are going to expect every user of your VI to know not only about C programming details in general but about the actual programming interface of your shared library function. A totally unusable LabVIEW VI as such!

No automatic wizard in the world could be thought this in any way, and even what I just wrote is usually only a reasonable guess based on the parameter naming, which in C has absolutely no meaning in any way. (The actual parameter names can be left away completely in the function prototype without any adverse effect when using the function, and the names in the function prototype can be also completely different to the names in the actual function declaration, if the programmer wants to do that to obfuscate his code even more.) The actual library documentation would hopefully explain in detail what each parameter is meant to mean but you can't point an automated tool at a PDF or HTML file and tell it to extract any exact programming information from the prosa text in there. 

Edited by Rolf Kalbermatter

Share this post


Link to post
Share on other sites

I never use the wizard.  I used the online documentation and wrote VIs by hand.

Share this post


Link to post
Share on other sites

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.