i am trying to get the full name of my gpu and my gpu usage using nvapi.dll.
i have encounter this post on this website: C# Performance Counter Help, Nvidia GPU.
he uses 2 sources, one in the dll itself (for getting the usage) and for full name he uses the header file of nvapi downloaded from the nevidia website.
There is any way i can avoid this duplication in my project?
using only the dll or using only the header files brought by nevidia.
Thanks for all the helpers
you can load DLL file dynamically when you need it,
in c# you can use .Net Reflection (if dll is developed in .Net framework), for example :
var DLL = Assembly.LoadFile(#"path\to\your.dll");
Type t = DLL.GetType("myAssembly.ClassName");
CustomType result = t.InvokeMember("methodName", BindingFlags.InvokeMethod, null, t, new object[] { #"method argument" });
if mentioned dll is not developed under .Net framework but you are forced to use .Net framework (for more information see this) :
int hModule = LoadLibrary(#"path\to\your.dll");
if (hModule == 0) return false;
IntPtr intPtr = GetProcAddress(hModule, "yourmethod_PTR");
if you want to use in c/c++ you can use following code :
HINSTANCE hGetProcIDDLL = LoadLibrary("path\\to\\your.dll");
if (hGetProcIDDLL == NULL) {
std::cout << "dll not found" << std::endl;
}
int a = function_to_call("arguments");
NOTE: if you want to load dll from unknown source I recommend to use c/c++, because in c/c++ you can manage your memory easier and free all your resources after dll loading,
I have found the list of functions id in https://github.com/processhacker/plugins-extra/blob/master/NvGpuPlugin/nvidia.c
In addition to
http://eliang.blogspot.com/2011/05/getting-nvidia-gpu-usage-in-c.html
i declared
typedef int(*nvAPI_GPU_getFullName_t)(int *handle , char* name); nvAPI_GPU_getFullName_t nvAPI_GPU_getFullName=NULL; nvAPI_GPU_getFullName=(nvAPI_GPU_getFullName_t)(*NvAPI_QueryInterface)(0xCEEE8e9FUL);
Related
Recently I have been trying to get some Point Cloud Library functionality going in my .NET framework application, and considering that there is no completely functional wrapper for PCL for C#, I made my own for a few functions as a test. Something like this:
[DllImport(DllFilePath, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr StatisticalOutlierFilter(IntPtr data, int length, int meanK = 50, float mulThresh = 1.0f);
Which calls a function from a C++ library, such as this:
EXPORT VectorXYZ* StatisticalOutlierFilter(VectorXYZ* data, int length, int meanK, float mulThresh) {
auto processedCloud = process.StatisticalOutlierFilter(data, length, meanK, mulThresh);
auto processedVector = convert.ToVectorXYZ(processedCloud);
return processedVector;
}
Where EXPORT is defined such for gcc:
#define EXPORT extern "C" __attribute__ ((visibility ("default")))
And relevant processing function from PCL is implemented such in a class (note that the returned is a boost shared pointer):
PointCloud<PointXYZ>::Ptr Processors::StatisticalOutlierFilter(VectorXYZ* data, int length, int meanK, float mulThresh) {
auto cloud = PrepareCloud(data, length);
PointCloud<PointXYZ>::Ptr cloud_filtered(new PointCloud<PointXYZ>);
StatisticalOutlierRemoval<PointXYZ> sor;
sor.setInputCloud(cloud);
sor.setMeanK(meanK);
sor.setStddevMulThresh(mulThresh);
sor.filter(*cloud_filtered);
return cloud_filtered;
}
This procedure works well with a dll built w/MSVC and running the whole thing on Windows, though the final target is gcc/Linux/Mono, where I get several errors of the following type (this is from mono debug):
'libavpcl_dll.so': '/usr/lib/libavpcl_dll.so: undefined symbol: _ZN3pcl7PCLBaseINS_8PointXYZEE13setInputCloudERKN5boost10shared_ptrIKNS_10PointCloudIS1_EEEE'.
I have investigated quite a bit so far, and have set my CmakeLists.txt to set(CMAKE_CXX_VISIBILITY_PRESET hidden) , therefore, I imagine, only functions I defined as EXPORT should be visible and imported - however, that is not the case, and I get the aforementioned errors. PCL was installed on Windows via vcpkg and on Xubuntu via apt. I am somewhat stumped as to what is the error source, considering the code runs well on windows, and builds without issue on Linux. Thanks.
I've been running into the same issue as you. I solved it by adding each reference library into the CMakeLists.txt file (I was missing the reference files which gave me the similar missing symbol issues).
I'm at the 'I don't know why this worked' stage but I can give you step by step implementation (I'm also trying to use DllImport into .NET on Linux).
Started with this:
https://medium.com/#xaviergeerinck/how-to-bind-c-code-with-dotnet-core-157a121c0aa6
Then added my in-scope files thanks to the main comment here: How to create a shared library with cmake?:
add_library(mylib SHARED
sources/animation.cpp
sources/buffers.cpp
[...]
)
run cmake .
run make -j$(grep -c ^processor /proc/cpuinfo)
copy path to .so file
DllImport path from above to my c# app
I have problem with Boost.Interprocess (v1.66) library which I use in my C/C++ library which I use in C# through Marshalling (calling C native code from C#).
I found the problem if I was using Boost.Interprocess named_semaphore for sync between processes. (in open_or_create mode)
If I use my C/C++ lib with another native C/C++ code everything works fine (under newest Windows 10, Linux (4+ kernel) and even Mac OS X (>=10.11)).
The problem occurred under Windows - with C# I have C wrapper around C++ code. If I use Marshalling with simple own-build EXE --> Everything works! But If I use The same C# code (with the same C lib) in the third party application as a DLL plugin I got segfault from get_bootstamp in named_semaphore.
So I have third-party C# SW for which I create plugins (C# DLL). In that plugin I use my C library through marshalling. Marshalling work fine in test C# project (which just call C functions from C lib) but same code segfault in third-party SW.
C Library workflow:
Init all necessary C structures
Start desired TCP server (native C/C++ app) using Boost.Process
Wait for server (through named_semaphore) <-- segfault
Connect to the server...
C# code has same workflow.
Found the problem
The problem occured in boost::interprocess::ipcdetail::get_booststamp (which is called in named_semaphore). here:
struct windows_bootstamp
{
windows_bootstamp()
{
//Throw if bootstamp not available
if(!winapi::get_last_bootup_time(stamp)){
error_info err = system_error_code();
throw interprocess_exception(err);
}
}
//Use std::string. Even if this will be constructed in shared memory, all
//modules/dlls are from this process so internal raw pointers to heap are always valid
std::string stamp;
};
inline void get_bootstamp(std::string &s, bool add = false)
{
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
if(add){
s += bootstamp.stamp;
}
else{
s = bootstamp.stamp;
}
}
If I debug to the line
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get()
booststamp.stamp is not readable. The size is set to 31, capacity is set to some weird value (like 19452345) and the data is not readable. If i step over to
s += bootstamp.stamp;
the segfault occured!
Found the reason
I debug once more and set debug point to the windows_bootstamp constructor entry and I got no hit so the stamp is not initialized (I guess).
Confirmation
If I change get_bootstamp to
inline void get_bootstamp(std::string &s, bool add = false)
{
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
std::string stamp;
winapi::get_last_bootup_time(stamp);
if(add){
s += stamp;
}
else{
s = stamp;
}
}
Recompile my lib and exe - everything works fine (without any problem).
My question is - what I am doing wrong? I read Boost.Interprocess doc really thoroughly but there are no advice/warnings about my problem (yeah there is "COM Initialization" in Interprocess doc but it not seems helpfull).
Or it's just a bug in Boost.interprocess and I may report it to Boost bug tracker?
Notice - if I start server manually (before I run C# code) It works without segfaults
Is there a way to embed my .net executable (C#/VB.Net) in a ntive binary like a C/C++ file which will load the .net assembly on startup?
Like building a native wall arround the .net assembly?
You could embed your .Net binary in the C++ project as a resource and load it runtime, but I doubt that is a recommended way to increase security.
Edit:
Someone asked for source code and suggested that I make a comment instead of an answer. I've just signed up for StackOverflow and I don't have enough reputation to make comments yet.
But here's some source I used at some point:
public static int RunInternalExe(byte[] rawData, params string[] args)
{
Assembly asm = Assembly.Load(rawData);
MethodInfo mi = asm.EntryPoint;
if (mi == null)
throw new Exception("Entry point not found");
ParameterInfo[] prms = mi.GetParameters();
object[] mtd_args = null;
if (prms.Length > 0)
mtd_args = new object[] { args };
object result = mi.Invoke(null, mtd_args);
if (result is int)
return (int)result;
return 0;
}
Embed the managed .exe in your wrapper .exe and pass the raw data to the proc above.
MyTools.RunInternalExe(Resources.ExeData);
Ofcourse, if you want your wrapper .exe to be non-managed you'd have to translate the code above to C++ or some other language of your choice, that's kind of above my head right now...
i have one dll that i build in C++ and one software that i built in C# - windows forms.
When i am calling to the dll via C# i got an fatal exception:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Here is the call:
[DllImport("dlltest.dll")]
[return: MarshalAs(UnmanagedType.SafeArray)]
private extern static string[] getFiles(string directory, string fileFilter, bool recrusive);
Here is the code from my DLL source:
extern "C" __declspec(dllexport) LPSAFEARRAY getFiles(string directory, std::string fileFilter, bool recrusive);
LPSAFEARRAY getFiles(string directory, std::string fileFilter, bool recrusive)
{
std::vector<std::string> filesArray;
if (recrusive)
getFilesByDirs(directory, fileFilter, false);
directory += "\\";
WIN32_FIND_DATAA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
std::string filter = directory + (recrusive ? "*" : fileFilter);
hFind = FindFirstFileA(filter.c_str(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
}
else
{
if (!recrusive)
{
if(isGoodForUs(directory + std::string(FindFileData.cFileName)))
{
filesArray.push_back(directory + std::string(FindFileData.cFileName));
}
}
while (FindNextFileA(hFind, &FindFileData) != 0)
{
if (!recrusive)
{
if(!isGoodForUs(directory + std::string(FindFileData.cFileName))) continue;
filesArray.push_back(directory + std::string(FindFileData.cFileName));
}
else
{
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)>0 && FindFileData.cFileName[0]!='.')
{
if(!isGoodForUs(directory + std::string(FindFileData.cFileName))) continue;
filesArray.push_back(directory + std::string(FindFileData.cFileName));
}
}
}
}
CComSafeArray<BSTR> a(filesArray.size());
std::vector<std::string>::const_iterator it;
int i = 0;
for (it = filesArray.begin(); it != filesArray.end(); ++it, ++i)
{
a.SetAt(i, A2BSTR_EX((*it).c_str()), FALSE);
}
return a.Detach();
}
Anyone know what is the problem?
The real question is why are you not using the .Net method that is the equivalent of your GetFiles() call
Directory.GetFiles Method (String path, String searchPattern, SearchOption searchOption)
You avoid degugging C++ code, the extra deployment issues and the execution penalty for switch between managed and unmanaged code.
EDIT ADDED
When you want to revert to using your C++ DLL from C# the most painless method if to create a C++ wrapper class that makes this as simple as possible. Microsoft recommends this over "platform invoke" that your were attempting to use (and ran into problems because of the std::string classes).
First, see this MSDN article for an overview of C#/C++ Interopability. Second, this articlegive a quick example of C++ class wrapping. Microsoft refers to using a C++ wrapping class at the method that "just works".
Having done lots of cross-platform programming in C, and C++ I have to wish you best of luck, it requires lots of effort to get it right. Since you are using C++ apparently as your cross platform interop layer, you would be well advised to create across-platform library for your interop code (keeping it separate from your application code). And second, create extern C interfaces to your interop as much as possible. This is really the "universal " calling format, no problems with name mangling, etc. A second question is how much interop do you need? Basic Files and Directories are not too hard. Sockets are another set of issues. Multithreading are another. I've used ACE before, it is C++ all the way, been around for a long time -- but it is a very powerful C++ interop library (among other things).
I am using .net Primary Interoperability Assembly for Excel in my code.
But, the application can be run on machine which doesn't have .net PIA for Excel installed.
I want to give an error message if it is not installed
Even though I am checking in GAC, to see if PIA is installed and only if it is present I am using Microsoft.Office.Interop.Excel related code. I am getting an error.
My problem is - I am getting error which is - Unhandled Exception - can't find could not load file or assembly Microsoft.Office.Interop.Excel
Any solution?
Thanks in advance!
I've used this Building block to load the x86 / x64 versions of hunspell in may NHunspell wrapper. maybe it is a good starting point for your own dynamic loader:
// Initialze the dynamic marshall Infrastructure to call the 32Bit (x86) or the 64Bit (x64) Dll respectively
SYSTEM_INFO info = new SYSTEM_INFO();
GetSystemInfo( ref info );
// Load the correct DLL according to the processor architecture
switch( info.wProcessorArchitecture )
{
case PROCESSOR_ARCHITECTURE.Intel:
string pathx86 = AppDomain.CurrentDomain.BaseDirectory;
if (!pathx86.EndsWith("\\"))
pathx86 += "\\";
pathx86 += Resources.HunspellX86DllName;
dllHandle = LoadLibrary(pathx86);
if (dllHandle == IntPtr.Zero)
throw new DllNotFoundException(string.Format(Resources.HunspellX86DllNotFoundMessage, pathx86));
break;
case PROCESSOR_ARCHITECTURE.Amd64:
string pathx64 = AppDomain.CurrentDomain.BaseDirectory;
if (!pathx64.EndsWith("\\"))
pathx64 += "\\";
pathx64 += Resources.HunspellX64DllName;
dllHandle = LoadLibrary(pathx64);
if (dllHandle == IntPtr.Zero)
throw new DllNotFoundException(string.Format(Resources.HunspellX64DllNotFoundMessage, pathx64));
break;
look at this delegate declarations:
internal delegate bool HunspellSpellDelegate(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)] string word);
And how to bind a library function to it
HunspellSpell = (HunspellSpellDelegate)GetDelegate("HunspellSpell", typeof(HunspellSpellDelegate));
I think this should work for you too, but you have to declare the complete interop code. You can check out the Nhunspell code to get a working sample of this technique:
NHunspell Web Site
I guess System.Type.GetTypeFromProgID("Excel.Application",true); method will throw exception if Excel is not present. You can use a try catch block and verify.
You shouldn't make static reference to Excel.Interop library. Instead of this, you should look for it in GAC, and load it in runtime. It's rather complicated, and there are no managed API to do this (by default).
Try to use this: fusion.dll API wrapper