I am trying to optimize a legacy application written in C which makes uses of regular stdio.h resp. fcntl.h functions. For special uses, I would like to inject a few extra hints from
https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants to newly opened file handles.
But those are available only to low-level Win32 APIs. Is there a way to pass the FILE_ATTRIBUTE_... options to the open() call somehow? Or is there somewhere a sane wrapper which would open a file handle "win32 way" with custom options and hand it over as integer file descriptor just like open() would do it?
There are two functions that convert between Win32 file handles and file descriptors:
intptr_t _get_osfhandle(int fd); will get you a HANDLEfrom a given fd
int _open_osfhandle(intptr_t osfhandle, int flags); will get you an fd from a HANDLE
Note that for both:
The _open_osfhandle call transfers ownership of the Win32 file handle
to the file descriptor. To close a file opened by using
_open_osfhandle, call _close
To close a file whose operating system (OS) file handle is obtained by
_get_osfhandle, call _close on the file descriptor fd. Never call CloseHandle on the return value of this function. ...
If you want to set the attributes at creation time, you would need to use CreateFile and then convert to a fd, because afaics there is no API to set attributes on a given HANDLE, there's only SetFileAttributes which operates on a name.
If you just wanna query the attributes, you can use GetFileInformationByHandle.
Related
I was checking in Go's source code, and it seems the standard out (os.Stdout) points to:
os.Stdout = os.NewFile(uintptr(syscall.Stdout), "/dev/stdout")
But from my understanding, this should only work for Unix-based systems. And yet, it's defined as a general variable.
Microsoft says Windows has a standard output device (stdout).
GetStdHandle function
STD_OUTPUT_HANDLE - The standard output device.
The Windows specific Go syscall.Stdout variable is:
go/src/syscall/syscall_windows.go:
var (
Stdout = getStdHandle(STD_OUTPUT_HANDLE)
)
See Go Build constraints for OS specific files.
The main important argument passed to NewFile is the first one, which is the file handle. The Windows syscall package correctly specifies a value for the standard output file (syscall.Stdout), so os just borrows it.
The point of the second argument is just to give the resulting *os.File value some kind of name that can be used, for example when calling os.Stdout.Name(), since the file handle doesn't carry a name by itself. You could argue that naming os.Stdout as "/dev/stdout" on Windows is confusing, but it's just a name that doesn't impact functionality.
I'm using NVRTC to compile a kernel. The relevant API call is:
nvrtcResult nvrtcCreateProgram (
nvrtcProgram* prog,
const char* src,
const char* name,
int numHeaders,
const char** headers,
const char** includeNames )
As you can see, the source is a raw string, and not associated with a file. That means that when you --generate-line-info, you get line numbers, but no related filename. And that means that if you then use, say, NSight Compute - you won't be able to see your kernel source code.
Obviously, neither NSight Compute itself, nor NVRTC itself, can figure out that the raw source is mirrored in some file. But there has to be some way to get around this:
Perhaps I'm missing something in the NVRTC API which can make the source <-> file association?
Perhaps we can manipulate the resulting compiled program (reasonably, not manually, or write-my-own-new-API) to make the association?
Perhaps we can shove the source code into the compiled program somehow?
Here's my initial workaround:
Place your source in a file, say my_kernel.cuh.
Create the string:
#include "my_kernel.cuh"
Compile just this string using NVRTC
Now, NVRTC is able to associate included files' sources with the files, so it's only a stub that will be missing in terms of source<->file association.
Caveat: You will need to be careful about paths - NVRTC's include paths, the working directory from which you invoke your program vs the directory of the source file etc.
It seems NVRTC does provides a default filename, such that if you place your source in the file with that name - NSight Compute may be able to find it.
The name is the one you passed to nvrtcCreateProgram() as the name argument.
So, if your kernel function (i.e. your __global__ function) is in my_kernel.cuh, and you place this file in the working directory of the profile program (which you tell NSight Compute about), or in one of the include directories you built your program with, you'll be able to read your source. If the original file's own directory is also one of the include directories, then you're in luck and you don't even have to make a copy.
Following the post ,
if I have header file,which has some functions implementations in it and should be included in several kernels(I mean these function are auxilary in all kernels and I don`t want to duplicate the code)
How I make this inclusion - can I keep the functions in header?Will the kernels and the header functions be compiled?
Can you specify (maybe by example) how I use the "-I" option in these case?
I am using VS2010(if its matter at all)
Note:Each kernel runs in different program
Yes, you can use headers in OpenCL for exactly what you are suggesting. Each kernel file will include the header and compile it.
The "-I" option is only used to specify the path for includes. If your includes are in your working directory it is not necessary. Here is an example:
/////////////////////////////////////////////////////////////////
// Load CL file, build CL program object, create CL kernel object
/////////////////////////////////////////////////////////////////
std::string sourceStr = FileToString(params.kernelFile);
cl::Program::Sources sources(1, std::make_pair(sourceStr.c_str(), sourceStr.length()));
cl::Program program = cl::Program(oclHandles.context, sources);
program.build(oclHandles.devices,"-I c:/Includes/");
I am using gSoap to generate ANSI C source code, that I would like to build within the LabWindows/CVI environment, on a Windows 7, 64 bit OS. The gSoap file stdsoap2.c includes several instances of the _setmode() function, with the following prototype:
int _setmode (int fd, int mode);
Where fd is a file descriptor, and mode is set to either _O_TEXT or _O_BINARY.
Oddly enough, even though LW/CVI contains an interface to Microsoft's SDK, this SDK does not contain a prototype to _setmode in any of its included header files, even though the help link to the SDK contains information on the function.
Is anyone aware of the method in LabWindows/CVI used to set file (or stream) translation mode to text, or binary.
Thanks,
Ryyker
Closing the loop on this question.
I could not use the only offered answer for the reason listed in my comment above.
Although I did use the SDK, it was not to select a different version of the OpenFile function, rather it was to support the use of a function that an auto-code generator used, _setmode() but that was not supported by my primary development environment (LabWindows/CVI).
So, in summary, my solution WAS to include the SDK to give me definition for _setmode as well as including the following in my non- auto-generated code:
#define _O_TEXT 0x4000 /* file mode is text (translated) */
#define _O_BINARY 0x8000 /* file mode is binary (untranslated) */
So, with the caveat that this post describes what I actually did, I am going to mark the answer #gary offered as the answer, as it was in the ball park. Thanks #gary.
It sounds like you just want to open a file as either ASCII or binary. So you should be able to replace the instances of _setmode() with the LW/CVI OpenFile() function as described here. Here's a short example reading a file as binary.
char filename = "path//to//file.ext"
int result;
result = OpenFile(filename, VAL_READ_ONLY, VAL_OPEN_AS_IS, VAL_BINARY);
if (result < 0)
// Error, notify user.
else
// No error.
Also note this warning from the page:
Caution The Windows SDK also contains an OpenFile function. If you
include windows.h and do not include formatio.h, you will get compile
errors if you call OpenFile.
Are file descriptors supported on windows? Why do things "seem to work" in Perl with fds?
Things like "fileno", "dup" and "dup2" were working but then randomly inside some other environment, stopped working. It's hard to give details, mostly what I'm looking for is answers from experienced Windows programmers and how file descriptors work/don't work on Windows.
I would guess that it's the PerlIO layer playing games and making it seem as though file descriptors work, but that's only a guess.
Example of what is happening:
open($saveout, ">&STDOUT") or die();
...
open(STDOUT, ">&=".fileno($saveout)) or die();
The second line die()s but only in certain situations (which I have yet to nail down).
Windows uses file descriptors natively. See Low-Level I/O on MSDN. They all report errors through the C variable errno, which means they show up in Perl's $!.
Note that you can save yourself a bit of typing:
open(STDOUT, ">&=", $saveout) or ...;
This works because the documentation for open in perlfunc provides:
If you use the 3-arg form then you can pass either a number, the name of a filehandle or the normal “reference to a glob.”
Finally, always include meaningful diagnostics when you call die! The program below identifies itself ($0), tells what it was trying to do (open), and why it failed ($!). Also, because the message doesn't end with a newline, die adds the name of the file and line number where it was called.
my $fakefd = 12345;
open(STDOUT, ">&=", $fakefd) or die("$0: open: $!");
This produces
prog.pl: open: Bad file descriptor at foo.pl line 2.
According to the documentation for _fdopen (because you used >&= and not >&), it has two failure modes:
If execution is allowed to continue, errno is set either to EBADF, indicating a bad file descriptor, or EINVAL, indicating that mode was a null pointer.
The second would be a bug in perl and highly unlikely because I don't see anywhere in perlio.c that involves a computed mode: they're all static strings.
Something appears to have gone wrong with $saveout. Could $saveout have been closed before you try to restore it? From your example, it's unclear whether you enabled the strict pragma. If it's not lexical (declared with my), are you calling a function that also monkeys with $saveout?