help with python ctypes and nvapi - python

My end goal is to query NVAPI for gpu usage and other statistics in python. See http://developer.nvidia.com/nvapi
from ctypes import WinDLL
nvapi = WinDLL("nvapi.dll")
print nvapi# <WinDLL 'nvapi.dll', handle 718a0000 at 27c0050>
print nvapi.nvapi_QueryInterface# <_FuncPtr object at 0x026D8E40>
print nvapi.nvapi_QueryInterface()# returns 0
print nvapi.NvAPI_Initialize# AttributeError: function 'NvAPI_Initialize' not found
print nvapi.NvAPI_SYS_GetChipSetInfo# AttributeError: function 'NvAPI_SYS_GetChipSetInfo' not found
Here is a copy of the header file available for download from the link above: http://paste.pound-python.org/show/7337/
At this point, I am just trying to familiarize myself with the api... so what am I doing wrong? I can't figure out how to call any of the functions listed in the header file.

Are you sure it's a WinDLL? From the header file, it looks like a standard C calling convention to me. Have you tried CDLL instead?
EDIT:
I see now. The header you pointed to isn't actually the interface for nvapi.dll--it is a wrapper around it that must be statically linked.
From the docs downloaded from NVIDIA's developer site:
Use a Static Link with Applications
NvAPI cannot be dynamically linked to applications. You must create a static link to the library and then call NvAPI_Initialize(), which loads nvapi.dll dynamically.
If the NVIDIA drivers are not installed on the system or nvapi.dll is not present when the application calls NvAPI_Initialize(), the call just returns an error. The application will still load.
I would guess that the actual calls in nvapi.dll are completely different than the ones exposed in this wrapper library. I can't seem to find any documentation on those though. Perhaps they are internal and change between systems.
If you want to use this interface, I'm not really sure what the best solution is. It's a static library and not a dynamic one, so ctypes wouldn't handle it unless you wrapped it in another DLL. I'm not an expert at native code with Python, so maybe someone else will have an easy fix. Sorry.

Taken from your comment:
NvAPI_Initialize call still fails.
saying the function is not found.
NvAPI_Initialize is not exported from the dynamic library nvapi.dll. It is a symbol contained in nvapi.lib, the static library shipped with the NVIDIA SDK, thus it's no wonder you are unable to call it using Python.
Honestly, the easiest route here is to create a small wrapper DLL in C, statically linking to nvapi.lib and exposing a friendly interface to Python.

Related

Using Python to access DLL functions with Pointers

I'm trying to build a Python app to access data inside a proprietary file format (*.abf, by Axon Instruments). The fine folks who specify the format have released a DLL that contains functions you can use to open these files, read/write, etc.
So far so good. I've read a number of posts on SO and around the web about using ctypes to import DLLs, and this seems to work fine - but many of the useful functions in the DLL I'm trying to interact with take integer pointers as an argument, and ctypes doesn't have a data type for interacting with that.
Am I out of luck? Do I need to write this app in a different language, or is there some way to hack this together in Python?
Thanks all,
-Steve
Look deeper. Ctypes does have Pointers.
from ctypes import *
f = c_float()
f_pointer = pointer(f) # full pointer functionality
f_byref = byref(f) # minimalistic pointer just for passing by reference

Python+Numpy modules in free pascal

Developing a module (.pyd) for Python in free pascal is fairly easy, see Developing Python Modules with Pascal. But if I want to interface with numpy, this is not that easy.
When using C to interface with numpy, you have to add #include <numpy/arrayobject.h> to the code, and also call import_array(); in the initialization function.
Is there a way to interface with numpy in pascal?
EDIT1
As mentioned in the comments under #wilberforce answer, the import_array function which is defined in the header files just imports multiarray.pyd module into the current interpreter and does some checking. It is easily translated into pascal and it works.
The numpy C-API functions are not present initially in pythonXX.dll, so they can't be linked statically. Static or dynamic linking with multiarray.pyd is not working for me.
So the updated question is: Is there a way to access the C-API functions embedded in multiarray.pyd from code which is not C?
Treat the numpy library like any other C library from Pascal's point of view - you need to include the header and declare import_array as an external cdecl function.
This guide covers the details.
You already need to have done some of this in order to have written a Python extension module so your Pascal code can use the Python API functions to interact with Python objects. You can see this in the cdecl; external PythonLib; modifiers in the example you link to. It's possible this wasn't clear while you were doing it.

How to dynamically interpose C functions from Python on Linux (without LD_PRELOAD)?

How do I, at run-time (no LD_PRELOAD), intercept/hook a C function like fopen() on Linux, a la Detours for Windows? I'd like to do this from Python (hence, I'm assuming that the program is already running a CPython VM) and also reroute to Python code. I'm fine with just hooking shared library functions. I'd also like to do this without having to change the way the program is run.
One idea is to roll my own tool based on ptrace(), or on rewriting code found with dlsym() or in the PLT, and targeting ctypes-generated C-callable functions, but I thought I'd ask here first. Thanks.
You'll find from one of ltrace developer a way to do this. See this post, which includes a full patch in order to catch dynamically loaded library. In order to call it from python, you'll probably need to make a C module.
google-perftools has their own implementation of Detour under src/windows/preamble_patcher* . This is windows-only at the moment, but I don't see any reason it wouldn't work on any x86 machine except for the fact that it uses win32 functions to look up symbol addresses.
A quick scan of the code and I see these win32 functions used, all of which have linux versions:
GetModuleHandle/GetProcAddress : get the function address. dlsym can do this.
VirtualProtect : to allow modification of the assembly. mprotect.
GetCurrentProcess: getpid
FlushInstructionCache (apparently a nop according to the comments)
It doesn't seem too hard to get this compiled and linked into python, but I'd send a message to the perftools devs and see what they think.

Is there a python wrapper for a FastLZ implementation

Looking to use FastLZ in Python, or something similar. Tried Google and didn't find anything. Wondering if there is another algorithm with similar performance available in Python?
What about using ctypes to call directly into fastlz.so (or .dll as the case may be)? It seems to have only 3 entry points, so wrapping them in ctypes should not be hard. Yes, SWIG or a custom C API wrapper should be almost as trivial, but ctypes lets you start experimenting right now even if you don't have a compiler (as long as you can get a working DLL/so of FastLZ for your platform)... hard to beat!-)
Blosc exposes FastLZ and several other compressors in Python.

Running unexported .dll functions with python

This may seem like a weird question, but I would like to know how I can run a function in a .dll from a memory 'signature'. I don't understand much about how it actually works, but I needed it badly. Its a way of running unexported functions from within a .dll, if you know the memory signature and adress of it.
For example, I have these:
respawn_f "_ZN9CCSPlayer12RoundRespawnEv"
respawn_sig "568BF18B06FF90B80400008B86E80D00"
respawn_mask "xxxxx?xxx??xxxx?"
And using some pretty nifty C++ code you can use this to run functions from within a .dll.
Here is a well explained article on it:
http://wiki.alliedmods.net/Signature_Scanning
So, is it possible using Ctypes or any other way to do this inside python?
If you can already run them using C++ then you can try using SWIG to generate python wrappers for the C++ code you've written making it callable from python.
http://www.swig.org/
Some caveats that I've found using SWIG:
Swig looks up types based on a string value. For example
an integer type in Python (int) will look to make sure
that the cpp type is "int" otherwise swig will complain
about type mismatches. There is no automatic conversion.
Swig copies source code verbatim therefore even objects in the same namespace
will need to be fully qualified so that the cxx file will compile properly.
Hope that helps.
You said you were trying to call a function that was not exported; as far as I know, that's not possible from Python. However, your problem seems to be merely that the name is mangled.
You can invoke an arbitrary export using ctypes. Since the name is mangled, and isn't a valid Python identifier, you can use getattr().
Another approach if you have the right information is to find the export by ordinal, which you'd have to do if there was no name exported at all. One way to get the ordinal would be using dumpbin.exe, included in many Windows compiled languages. It's actually a front-end to the linker, so if you have the MS LinK.exe, you can also use that with appropriate commandline switches.
To get the function reference (which is a "function-pointer" object bound to the address of it), you can use something like:
import ctypes
func = getattr(ctypes.windll.msvcrt, "##myfunc")
retval = func(None)
Naturally, you'd replace the 'msvcrt' with the dll you specifically want to call.
What I don't show here is how to unmangle the name to derive the calling signature, and thus the arguments necessary. Doing that would require a demangler, and those are very specific to the brand AND VERSION of C++ compiler used to create the DLL.
There is a certain amount of error checking if the function is stdcall, so you can sometimes fiddle with things till you get them right. But if the function is cdecl, then there's no way to automatically check. Likewise you have to remember to include the extra this parameter if appropriate.

Categories