LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Capturing STOUT/STDERR from C DLLs

I realize this question has been asked several times in that past.  The last thread I could file was 6 years old and thought it would be a better idea to start a new thread rather than revive that one.  I am however starting with code snippets I took from this thread:  

 

https://forums.ni.com/t5/LabVIEW/Redirecting-stdout-stderr-stdin-to-from-LabVIEW-in-dlls/m-p/1768662

 

snippet.png

 

 

Pretty much that is what I'm wanting to do, however I am struggling to make it work.  When it executes, I see LabVIEW open the pipe and then pend on reading output from it.  Then the C library node calls a routine within a dll that I've build that contains the code:

 

extern "C" __declspec(dllexport)int testReadParams(VOID )
{
  fprintf(stdout, "Test!");
  fflush(stdout);
  return(10);
}

The C Library node runs this routine repeatedly, and each time I do see the value '10' returned.  The pend on reading the pipe will not return until I hit the stop button - pushing some text from LabVIEW into stdout, allowing the pend to return.  I'm not sure what I'm doing wrong but I've been struggling with this off and on for months.  Any help, or alternate ideas would be greatly appreciated.

 

-Tim

0 Kudos
Message 1 of 47
(9,024 Views)

Do dll's even have a stdin, stdout and stderr? I've never tried, but to me it sounds very weird.

Regards,

Wiebe.

0 Kudos
Message 2 of 47
(8,971 Views)

@scorn001 wrote:

 

  Any help, or alternate ideas would be greatly appreciated.

 


Can you make the dll\exe yourself? I'd go for a named pipe (very easy in LV with .net).

Your use case is not clear. What exactly are you trying to do? If you just want to start something with an input and an output, clearly you could use the dll's inputs and outputs. If you want to start something, and then communicate with it, there are a number of solutions (named pipes, memory mapping, TCP\IP, ...) It all depends on the exact requirements.

Regards,

Wiebe.

0 Kudos
Message 3 of 47
(8,969 Views)

We have an API that we originally developed for Linux but we build for Windows in order to link Windows GUI apps against and be able to use a graphical interface with our API.  The API is pretty large, and uses a lot of printfs to communicate debug information back to the user on the console/tty.

 

I'm now wanting to make calls into the API with LabVIEW, and have a LabVIEW panel to perform the same tasks - and so far I'm able to make some calls into the API with the Call Library Function Node vi, but when I encounter a problem, without being able to see output from the console/STDOUT/printf, I have no visibility into what is going wrong with the function.  

 

Also, it would be very useful, generally speaking, to be able to have a frame in the LabVIEW panel that reports this information, so that when a problem is encountered, you can see what is happening with the lower level API.

 

 

0 Kudos
Message 4 of 47
(8,957 Views)

I think redirecting the stdout\stderr of a dll might be hard. For an exe, you'd be able to start the process with options so you have more control.

 

But I'd expect the .dll will be writing to LabVIEW's stdin\stdout, since it's executed in the same process. So you need to get handles to those. getstdhandle seems to do that. Then you need to ReadFile to get the data.

 

However, LabVIEW itself might write to the stdout\stderr. I know LabVIEW does that when certain options are on. I don't know if there will be anything when those options are off (this will be default). It might interfere. I'll take the chance, IIRC, the stdout will only be used when certain commands are given (and options are on).

 

0 Kudos
Message 5 of 47
(8,945 Views)

Yeah, in trying to make this work it's pretty obvious that calling an *.exe via cmd is the easiest as far as getting stdout & stderr.  The problem is that for us, it's also probably the most inefficient, to the point of being prohibitive.  We have 50+ commands in our API, they all must have certain structures/resources put in place and configured to get the commands routed where they need to go, and pull data back - this would all have to be setup, network sockets opened and closed, resources loaded and unloaded, with each and every command, and there can be 1000s or more every second - more when running automated procedures.  I think calling an exe each time we need to adjust a parameter within our product would be problematic. 

 

Currently I am pursuing the getstdhandle method.  I was able to get this to work from within the DLL using the WriteFile call, and pushing that to the STDOUT handle.  Now I just need to get it so that my printfs will be pushed there.

0 Kudos
Message 6 of 47
(8,937 Views)

Currently I am pursuing the getstdhandle method.  I was able to get this to work from within the DLL using the WriteFile call, and pushing that to the STDOUT handle.  Now I just need to get it so that my printfs will be pushed there.


I've tried to get stdout using .net (console.write() and also process.stdoutredirect etc.), but didn't succeed. I'm not really sure if it should do anything, since I'm not sure how to make LabVIEW put anything on the stdout...

Should printfs output to stdout by default?

0 Kudos
Message 7 of 47
(8,933 Views)

On *nix machines yes, and I'm pretty sure this works on windows too.  You can normally use _dup2() on Windows (or Linux) to redirect all printfs out to any other entity with a file descriptor. 

 

You can make LabVIEW (in theory) output something to STDOUT or STDERR by using the Call Library Function Node dll and making calls into the Windows API - kernel32.dll, of course since LabVIEW doesn't really have any form of a console or terminal - you'd have to then read STDOUT I guess to push that into a text window of some sort.  I'm not really trying to make LabVIEW output to STDOUT, I'm trying to get it to read STDOUT, or a pipe, or anything, that is setup within a my dll, that I will then have STDOUT forwarded, or redirected to.

 

I think absolute worst case, I can have my dll output it's printfs to a file, and then have LabVIEW read that file.  It just seems really inefficient to do it that way, and then I worry about both sides trying to access it at the same time, particularly where there is LOTS of debug flowing.

 

I've seen this question raised repeatedly.  It really seems like if LabVIEW is going to have the ability to call into C/C++ dlls they would have the ability natively to siphon the STDOUT and STDERR - and push stuff to STDIN.  These are all pretty fundamental and very heavily used concepts in text based programming - printf and cout.  I'm sure it's probably not quite that simple however.

 

 

0 Kudos
Message 8 of 47
(8,929 Views)

A DLL doesn't have a stdin/stdout/stderr in itself. it inherits the stdin/stdout/stderr of whatever process the DLL is called from. But LabVIEW is a standard Windows GUI application and Windows does not allocate any stdIO handles for GUI applications by default.

I believe you can assign them later by a calling some Windows API functions but am not sure. Another option is to hack the PE header of your LabVIEW executable to indicate to Windows that it should allocate stdIO handles anyhow. Most likely there is also a possibility to add something in a manifest file to achieve the same.

 

What I usually do is adding a function to the DLL that can be called from LabVIEW to pass a user even refnum to it and in the DLL have a replacement printf() macro that checks this refnum and sends the string to LabVIEW through PosLVUserEvent() if it is not NULL, otherwise calls the normal printf(). The difficulty with that is that achieving fully variadic operation like the printf() function has is not really possible with standard C macro logic.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 9 of 47
(8,922 Views)

rolfk wrote:

I believe you can assign them later by a calling some Windows API functions but am not sure.


Rolf, AllocConsole seems to do that.

See Adding Console I/O to a Win32 GUI App.

Message 10 of 47
(8,913 Views)