views:

68

answers:

1

I have a Perl script and needed to call a method that's in a .NET assembly. I found this technique but it's quite involved for a one-off Perl script so I didn't use it. I ended up writing a trivial .NET console app as a wrapper for the call I need and have my Perl script communicate with the wrapper, using Console.In / Console.Out / IPC::Open2.

This turned out to be problematic because .NET's StreamReader.ReadToEnd method did not seem able to detect the end-of-file on Console.In, even after my Perl script closed its end of the pipe!

I ended up hacking a solution that worked for my purposes, but is there a better way to call .NET from Perl?

+3  A: 

"StreamReader.ReadToEnd method did not seem able to detect the end-of-file on Console.In"

You seem to have been able to interface with .NET. But you called StreamReader.ReadToEnd on a console input. That can be problematic, even without Perl. An excerpt of why this is:

ReadToEnd assumes that the stream knows when it has reached an end. For interactive protocols, in which the server sends data only when you ask for it and does not close the connection, ReadToEnd might block indefinitely and should be avoided.

Perhaps your code is right, but you need to use a different method for your purpose.

Edit:

"I ended up writing a trivial .NET console app as a wrapper "

It seems to me that you try to communicate between the two (Perl and .NET). The protocol you chose (Console.In/Out) may work, but you should use StreamReader.Read or StreamReader.ReadLine in your .NET application in a loop, that way you can easily detect when the stream is closed. The Read operations will return null when they are at EOF.

Alternatively, you can use any method that pleases you in Perl and have it called from .NET. I.e., you inverse the logic and .NET just asks by interfacing with your Perl code, for input. Then you can stick with Perl for your main programming task. You can do this using PerlSharp.

Abel
I ended up passing a byte length as a command-line parameter to the wrapper console app, and having the console app call "ReadBlock" instead of "ReadToEnd"
JoelFan
I don't think switching to Read / ReadLine will work any better then ReadToEnd. You say the Read operations return null when they are at EOF, but the problem is they can't detect EOF on a pipe. They would just block when I finish writing, just like ReadToEnd
JoelFan
@JoelFan: That's not according to the .NET documentation, see the link on ReadToEnd in my post. However, I can do a little test of course, see what comes up. Btw, `ReadBlock` basically works the same as `Read`, it internally calls `Read` anyway, so if that works for you, both approaches should work. Mmm, things considering, I assume only without the EOF-flag ;-)
Abel
The reason ReadBlock works for me is because I am passing the number of bytes to read into my wrapper and feeding that count into ReadBlock. The result of this is that I don't end up invoking the (faulty) EOF detection of StreamReader AT ALL.
JoelFan