What I need is the 2 number version (e.g. 368.39) of the Nvidia drivers retrieved in a c++ program. Using Windows 7 64b.
Here is how to do this in 64bit applications using NVML library from Nvidia.
However, the nvml.dll distributed with Nvidia drivers is 64bit only. There is no way to dynamically load this library in my 32bit program. This is assuming your computer is 64bit. I have not tested this on a 32bit machine.
So far the NVML seems to be the only library that allows retrieving this information. What other methods are there to get this if any?
// ---------------------------------------------------------------------
// (windows) how to get the nvidea driver version?
// ---------------------------------------------------------------------
#define C(a) {std::cout<<a<<std::endl;} // for easy print out to console
template <class T> inline std::string TOSTR(const T fp){ // a macro
std::ostringstream o;
o.setf(std::ios_base::fixed, std::ios_base::floatfield);
o << fp; // << ends; (null-terminator character)
return std::string(o.str());
}
// ---------------------------------------------------------------------
#pragma comment(lib,"nvapi.lib") // needed !
#include <nvapi.h> // needed !
// you have to start nvapi:
NvAPI_Status ret(NVAPI_OK);
ret = NvAPI_Initialize();
if(ret != NVAPI_OK) {
NvAPI_ShortString string;
NvAPI_GetErrorMessage(ret, string);
printf("NVAPI NvAPI_Initialize: %s\n", string);
}
NvAPI_Status s;
NvU32 v; // version
NvAPI_ShortString b; // branch
s = NvAPI_SYS_GetDriverAndBranchVersion(&v, b);
if(s != NVAPI_OK) {
NvAPI_ShortString string;
NvAPI_GetErrorMessage(s, string);
printf("NvAPI_SYS_GetDriverAndBranchVersion: %s\n", string);
}
C("Nvidea driver version: " + TOSTR(v)); // app, console output
// ...hope i can help ....
I assume you are using windows since you mention ".dll"
In windows you should be able to use WMI to get any hardware information you need. For a display adapter use the Win32_VideoController WMI class it has a string field called driverversion that should have what you want.
https://msdn.microsoft.com/en-us/library/aa394512(v=vs.85).aspx
Related
I have a cpp program that uses fopen_s to open and read a file created under the directory C:\Windows\System32\config\systemprofile\AppData\Roaming.
My program needs to be compatible with winx64 and win32.
When I run this program with a system account (run using PSTools\PSExec -i -s C:\windows\system32\cmd.exe) and the Win32 compiled version of the program, fopen_s() on any file inside "C:\Windows\System32\config\systemprofile\AppData\Roaming" returns an error code 2, even though the file is present.
However, when I run the x64 compiled version of the same program, it works fine and fopen_s() is able to find and open the same file.
I am sure there are no mistakes as far as passing a valid filename to fopen_s() and I have verified this.
I make sure that the int variable that stores the return value from fopen_s() is set to 0 every time before calling fopen_s(). I am calling fopen_s() in "r" mode.
Also, elsewhere in the same program I am able to create files under the same directory.
I am using VS2019 and cpp +11 to compile my program.
My system is running windows 10 (64-bit) on an x64 processor (Intel(R) Xeon(R) Gold 6136)
Why would a win32 application fail to read a file created under "C:\Windows\System32\config\systemprofile\AppData\Roaming" with a system account while the x64 version of the same application works fine?
Code snippet:
int FileOpenFunc(FILE ** ppFile, std::string sFilename, std::string sOpenMode)
{
int errOpen = 0;
#ifdef _WIN32
errOpen = fopen_s(ppFile, sFilename.c_str(), sOpenMode.c_str());
#else
*ppFile = fopen(sFilename.c_str(), sOpenMode.c_str());
errOpen = errno;
#endif
return errOpen;
}
void func()
{
std::string sFileName = "C:\\Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\Check\\sample.txt";
int errFopenErrNo = 0;
FILE* fp = NULL;
errFopenErrNo = FileOpenFunc(&fp, sFileName, "r");
if (fp!= NULL)
{
//do something
}
else
{
//do something else
}
}
I have to read some data line by line from a large file (more than 7GB), it contains a list of vertex coordinates and face to vertex connectivity information to form a mesh. I am also learning how to use open, mmap on Linux and CreateFileA, CreateFileMapping, MapViewOfFile on Windows. Both Linux and Windows versions are 64bit compiled.
When I am on Linux (using docker) with g++-10 test.cpp -O3 -std=c++17 I get around 6s.
When I am on Windows (my actual PC) both with (version 19.29.30037 x64) cl test.cpp /EHsc /O3 /std:c++17 I get 13s, and with clang++-11 (from Visual Studio Build Tools) I get 11s.
Both systems (same PC, but one is using docker) use the same exact code except for generating the const char* that represents the memory array and the uint64_t size that reprents the memory size.
This is the way I switch platforms:
// includes for using a specific platform API
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// using windows handle void*
#define handle_type HANDLE
#else
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
// using file descriptors
#define handle_type int
#endif
Specifically the code for getting the memory in an array of char-s is:
using uint_t = std::size_t;
// open the file -----------------------------------------------------------------------------
handle_type open(const std::string& filename) {
#ifdef _WIN32
// see windows file mapping api for parameter explanation
return ::CreateFileA(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // private access
#else
return ::open(filename.c_str(), O_RDONLY);
#endif
}
// get the memory size to later have a bound for reading -------------------------------------
uint_t memory_size(handle_type fid) {
#ifdef _WIN32
LARGE_INTEGER size{};
if (!::GetFileSizeEx(fid, &size)) {
std::cerr << "file not found\n";
return size.QuadPart;
}
return size.QuadPart;
#else
struct stat sb;
// get the file stats and check if not zero size
if (fstat(fid, &sb)) {
std::cerr << "file not found\n";
return decltype(sb.st_size){};
}
return sb.st_size;
#endif
}
// get the actual char array to access memory ------------------------------------------------
const char* memory_map(handle_type fid, uint_t memory_size) {
#ifdef _WIN32
HANDLE mapper = ::CreateFileMapping(fid, NULL, PAGE_READONLY, 0, 0, NULL);
return reinterpret_cast<const char*>(::MapViewOfFile(mapper, FILE_MAP_READ, 0, 0, memory_size));
#else
return reinterpret_cast<const char*>(::mmap(NULL, memory_size, PROT_READ, MAP_PRIVATE, fid, 0));
#endif
}
I am completely new to this sort of parsing and was wondering if I am doing something wrong in choosing the parameters in the Windows API (to mimic the behaviour of mmap) or if the difference in time is a matter of compilers/systems and have to accept it?
The actual time to open, get the memory size, and the memory map is negligible both on Linux and on Windows, the rest of the code is identical, as it only operates using the const char* and size_t info.
Thanks for taking the time to read. Any tip is greatly appreciated and sorry if anything is unclear.
Maybe you should take a look at https://github.com/alitrack/mman-win32 which is a mmap implementation for Windows. That way you don't need to write different code for Windows.
I am writing a code for macOS application.
The application would be running on M1 based Macs as well as Intel based Macs also.
What would be the switch to differentiate M1 and Intel?
if (M1)
{
do something for M1
}
else if (Intel)
{
do something for Intel
}
I think, you can use __arm__ to detect arm architecture:
#ifdef __arm__
//do smth on arm (M1)
#else
//do smth on x86 (Intel)
#endif
I was just fooling around with this and found this reference for Objective-C from apple that seemed to work with clang for C++.
// Objective-C example
#include "TargetConditionals.h"
#if TARGET_OS_OSX
// Put CPU-independent macOS code here.
#if TARGET_CPU_ARM64
// Put 64-bit Apple silicon macOS code here.
#elif TARGET_CPU_X86_64
// Put 64-bit Intel macOS code here.
#endif
#elif TARGET_OS_MACCATALYST
// Put Mac Catalyst-specific code here.
#elif TARGET_OS_IOS
// Put iOS-specific code here.
#endif
https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary
I specifically checked to see if TARGET_CPU_ARM64 was defined in my header.
Hopefully this helps someone.
If you need a runtime check instead of compile time check, you can think of using something like below
#include <sys/sysctl.h>
#include <mach/machine.h>
int main(int argc, const char * argv[])
{
cpu_type_t type;
size_t size = sizeof(type);
sysctlbyname("hw.cputype", &type, &size, NULL, 0);
int procTranslated;
size = sizeof(procTranslated);
// Checks whether process is translated by Rosetta
sysctlbyname("sysctl.proc_translated", &procTranslated, &size, NULL, 0);
// Removes CPU_ARCH_ABI64 or CPU_ARCH_ABI64_32 encoded with the Type
cpu_type_t typeWithABIInfoRemoved = type & ~CPU_ARCH_MASK;
if (typeWithABIInfoRemoved == CPU_TYPE_X86)
{
if (procTranslated == 1)
{
cout << "ARM Processor (Running x86 application in Rosetta)";
}
else
{
cout << "Intel Processor";
}
}
else if (typeWithABIInfoRemoved == CPU_TYPE_ARM)
{
cout << "ARM Processor";
}
}
getting information if operating system is 32-bit or 64-bit from Qt Framework, to be portable on different OS's
I can get from Qt information wether the application has been build for as 32 or 64-bit (QSysInfo::buildCpuArchitecture()) or wether the CPU is 32 or 64-bit (QSysInfo::currentCpuArchitecture()), the operating system name(QSysInfo::prettyProductName()) but I haven't find how to determine if the operating system is 32 or 64-bit with Qt (should be portable!).
Is there any function in Qt to get that information?
Thanks for your time.
qDebug() << "QSysInfo::buildCpuArchitecture():" << QSysInfo::buildCpuArchitecture();
qDebug() << "QSysInfo::currentCpuArchitecture():" << QSysInfo::currentCpuArchitecture();
qDebug() << "QSysInfo::buildAbi():" << QSysInfo::buildAbi();
qDebug() << "QSysInfo::prettyProductName():" << QSysInfo::prettyProductName();
// the result with MinGW 32-bit:
// QSysInfo::buildCpuArchitecture(): "i386"
// QSysInfo::currentCpuArchitecture(): "x86_64"
// QSysInfo::buildAbi(): "i386-little_endian-ilp32"
// QSysInfo::prettyProductName(): "Windows 10"
// the result with VC++ 64-bit:
// QSysInfo::buildCpuArchitecture(): "x86_64"
// QSysInfo::currentCpuArchitecture(): "x86_64"
// QSysInfo::buildAbi(): "x86_64-little_endian-llp64"
// QSysInfo::prettyProductName(): "Windows 10"
Although the name suggests otherwise, currentCpuArchitecture does not tell you whether the CPU is 32bit or 64bit, but will tell you about the bitness of the operating system.
QString QSysInfo::currentCpuArchitecture()
Returns the architecture of the CPU that the application is running
on, in text format. Note that this function depends on what the OS
will report and may not detect the actual CPU architecture if the OS
hides that information or is unable to provide it. For example, a
32-bit OS running on a 64-bit CPU is usually unable to determine the
CPU is actually capable of running 64-bit programs.
http://doc.qt.io/qt-5/qsysinfo.html#currentCpuArchitecture
After many trials, I have found a solution, which gives also the right result with a 32-bit application an 64-bit Windows:
#if defined(Q_OS_WIN)
inline bool isWow64Process()
{
// https://learn.microsoft.com/en-us/windows/desktop/api/wow64apiset/nf-wow64apiset-iswow64process
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if( NULL != fnIsWow64Process )
{
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
{
// we couldn't get the pointer to the function,
// we assume that app is not running as
// WOW64 process and return therefore FALSE
bIsWow64 = FALSE;
}
}
return bIsWow64;
}
#endif // (_MSC_VER)
QString osInfo()
{
#if defined(Q_OS_WIN)
QString osBitness( QSysInfo::buildAbi().contains("ilp32") && !isWow64Process()? "32-bit" : "64-bit" );
return QString( QSysInfo::prettyProductName() + " - " + osBitness);
#else // we do not know how to get OS bitness on Linux and OS-X (we do not mean processor, neither application, but OS!)
return QSysInfo::prettyProductName();
#endif
}
I want to get driver version of nVidia video card.
So I used WMI and get data from "DriverVersion" obejct of "Win32_VideoController" class.
But it was like "9.18.13.1106"(file version) and what I wanted is something like "311.06"(treiber version).
Where can I get that information?
If it is impossible on WMI, I want to know other way to get that.
Thanks.
You can do this using NVML from nVidia's Tesla Deployment Kit. You can retrieve the internal driver version (the one you're accustomed to seeing for an nVidia driver) with code like this:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <nvml.h>
#include <windows.h>
namespace {
typedef nvmlReturn_t (*init)();
typedef nvmlReturn_t (*shutdown)();
typedef nvmlReturn_t (*get_version)(char *, unsigned);
class NVML {
init nvmlInit;
shutdown nvmlShutdown;
get_version nvmlGetDriverVersion;
std::string find_dll() {
std::string loc(getenv("ProgramW6432"));
loc += "\\Nvidia Corporation\\nvsmi\\nvml.dll";
return loc;
}
public:
NVML() {
HMODULE lib = LoadLibrary(find_dll().c_str());
nvmlInit = (init)GetProcAddress(lib, "nvmlInit");
nvmlShutdown = (shutdown)GetProcAddress(lib, "nvmlShutdown");
nvmlGetDriverVersion = (get_version)GetProcAddress(lib, "nvmlSystemGetDriverVersion");
if (NVML_SUCCESS != nvmlInit())
throw(std::runtime_error("Unable to initialize NVML"));
}
std::string get_ver() {
char buffer[81];
nvmlGetDriverVersion(buffer, sizeof(buffer));
return std::string(buffer);
}
~NVML() {
if (NVML_SUCCESS != nvmlShutdown())
throw(std::runtime_error("Unable to shut down NVML"));
}
};
}
int main() {
std::cout << "nVidia Driver version: " << NVML().get_ver();
}
Note that if you're writing this purely for your own use on a machine where you're free to edit the PATH, you can simplify this quite a bit. Most of the code deals with the fact that this uses NVML.DLL, which is in a directory that's not normally on the path, so the code loads that dynamically, and uses GetProcAddress to find the functions in it that we need to use. In this case, we're only using three functions, so it's not all that difficult to deal with, but it still at drastically increases the length of the code.
If we could ignore all that nonsense, the real code would just come out to something on this general order:
nvmlInit();
nvmlSystemGetDriverVersion(result, sizeof(result));
std::cout << result;
nvmlShutdown();
Anyway, to build it, you'll need a command line something like:
cl -Ic:\tdk\nvml\include nv_driver_version.cpp
...assuming you've installed the Tesla Deployment Kit at c:\tdk.
In any case, yes, I've tested this to at least some degree. On my desktop it prints out:
nVidia Driver version: 314.22
...which matches what I have installed.
To get the Nvidia driver version through C++ on Win64:
Download NVAPI https://developer.nvidia.com/rtx/path-tracing/nvapi/get-started, a few MB
The main folder of the downloaded archive contains several header files, one of which is nvapi.h. Those headers are needed for compilation. The subfolder amd64 contains nvapi64.lib, which is needed for linking. The following code will now show the driver version:
#include <iostream>
extern "C" {
#include "nvapi.h"
}
int main() {
NvAPI_Status status = NVAPI_OK;
NvAPI_ShortString str;
status = NvAPI_Initialize();
if (status == NVAPI_LIBRARY_NOT_FOUND) {
//in this case NvAPI_GetErrorMessage() will only return an empty string
std::printf("error no nvidia driver found\n");
} else if (status != NVAPI_OK) {
NvAPI_GetErrorMessage(status, str);
std::printf("error initializing nvapi: %s\n", str);
}
NvU32 version = 0;
NvAPI_ShortString branch;
status = NvAPI_SYS_GetDriverAndBranchVersion(&version, branch);
if (status != NVAPI_OK) {
NvAPI_GetErrorMessage(status, str);
std::printf("error getting driver version: %s\n", str);
} else {
std::printf("driver version %d.%d", version / 100, version % 100);
}
}