09-07-2017 10:24 AM
wiebe@CARYA wrote:
I think the DLL itself can redirect it's outputs (to a named pipe). So I think you could make a function that set's up the redirection. Then, the rest of the dll could stay the same?
The redirect won't need to re-setup each time I call into the DLL? I'd assumed that it would. I'll test that.
09-07-2017 12:54 PM
This actually appears to work with my test case. If I just make a call into the dll to setup the redirect, then it appears as though the rest of the calls into the dll will have their stdout routed to the pipe I'm reading.
This I believe resolves my issue.
Thank you again.
09-08-2017 02:11 AM
@scorn001 wrote:
This actually appears to work with my test case. If I just make a call into the dll to setup the redirect, then it appears as though the rest of the calls into the dll will have their stdout routed to the pipe I'm reading.
This I believe resolves my issue.
Thank you again.
The DLL stays the same process once it's loaded. So that is why it works. It will probably only work if the VI is set to run in UI thread. I think running in other thread instantiates new instances for each time you use it (not sure might test that).
Could you post the code of the function in the DLL? I think it would help out a lot of people in the future.
09-08-2017 03:30 AM
wiebe@CARYA wrote:
The DLL stays the same process once it's loaded. So that is why it works. It will probably only work if the VI is set to run in UI thread. I think running in other thread instantiates new instances for each time you use it (not sure might test that).
That doesn't sound quite right. A specific DLL is only mapped once into a process. Unless it uses a SxS (side by side) configuration, only the DLL name is important for Windows to decide if a DLL is already mapped into a process space. With SxS a DLL can be loaded multiple times into the process, once for every version of the DLL that some part of the application links to.
And the Standard C stdio fd's are most likely also C runtime library global but as explained earlier you can easily end up with multiple C runtime libraries linked into the same application. This has also other consequences such as not being able to pass memory pointers allocated in the context of one C runtime library to a context that links to a different C runtime library to deallocate this pointer. Same applies for file descriptors opened with C runtime library functions.
09-08-2017 03:31 AM
wiebe@CARYA wrote:
The DLL stays the same process once it's loaded. So that is why it works. It will probably only work if the VI is set to run in UI thread. I think running in other thread instantiates new instances for each time you use it (not sure might test that).
That doesn't sound quite right. A specific DLL is only mapped once into a process. Unless it uses a SxS (side by side) configuration, only the DLL name is important for Windows to decide if a DLL is already mapped into a process space. With SxS a DLL can be loaded multiple times into the process, once for every version of the DLL that some part of the application links to.
And the Standard C stdio fd's are most likely also C runtime library global but as explained earlier you can easily end up with multiple C runtime libraries linked into the same application. This has also other consequences such as not being able to pass memory pointers allocated in the context of one C runtime library to a context that links to a different C runtime library to deallocate this pointer. Same applies for file descriptors opened with C runtime library functions.
09-08-2017 04:37 AM
@Rolfk:
So you're saying (among other things) that "run in any thread" would not make a difference? That it should work (but obviously might "mix" results)?
I thought "run in any thread" had a re-entrant like effect (separate memory space). Haven't given it much thought lately tough. If I understand correctly it only enables parallel execution. That does make more sense.
I guess at least "specify path on diagram" could be tricky, because LV might unload the dll if it's not used anymore? I think LV only unloads dll's when the call library node is called with another path.
09-08-2017 05:32 AM - edited 09-08-2017 05:50 AM
Run in any thread really only means that the Call Library Node is free to execute in whatever thread the VI is at that moment executing (and that will consume that thread exclusively for the function call until it returns back to LabVIEW as LabVIEW can't do its cooperate multitasking magic during the Call Library Node call, it doesn't have any hooks into the DLL to suspend its execution and assign the thread to other code clumps to execute).
As far as LabVIEW is concerned the DLL function is a complete black box that gets passed the input parameters on the stack (some registers too for 64 bit) and at some point returns with an optional integer return value in the EAX (or RAX for 64-bit) register, or the ST0/IMM0 register for floating point return values. For output parameters (parameters wired on the right side of the Call Library Node and defined as reference parameters in the C code) the parameters then returned back to the diagram.
Nowhere is any LabVIEW specific reentrancy (memory space) involved unless you start to play with the Callback functions in the Call Library Node configuration dialog and use the InstanceDataPtr in the call to your Call Library Node.
But functions that are called from any thread need to be fully reentrant capable to be safe to be called in that way, although that is not a strict requirement if you can guarantee in other ways that no global resource can be accessed concurrently by multiple/concurrent calls to any function in a DLL. But proofing that for not fully reentrant functions is anything but trivial and also usually hard to enforce for a casual LabVIEW programmer who is going to use your LabVIEW VI library in many very obscure ways.
Distributing a VI library that has the requirements that you have to call all the functions sequentially through some means like error cluster wiring in order to not crash is not very user friendly.
On the other hand that you have to start a data acquisition successfully, before you can expect to retrieve any meaningful data without getting an error is of course quite logical but that is not what this discussion is about. Returning an error because certain prerequests have not been fullfilled is fully legal, but crashing because of that is not!