Too many arguments in my function - Python - python

I am trying to access my function in a dll and pass by value as integer in it. But I am getting a ValueError as:
Procedure probably called with too many arguments (4 bytes in excess)
My python .py script is as below:
func2.restype = c_int
func2.argtypes = [c_int]
func2(3)
...
My actual function in the dll is just a simple function like:
int DLLfun2(int argtest) { return argtest + 1; };
...
Looks like a simple problem, but I'm guessing I am missing out on something. Kindly help.
Cheers.

Looks weird because integer should be automatically cast, but try with a func2(c_int(3))
EDIT :
According to the ctypes doc, this exception could be raised because of a wrong calling convention (cdecl instead of stdcall). But the function is still called (just a sort of warning :s)
Be sure of you declaration in your dll.
If you load your library with windll, it must use stdcall calling convention, otherwise, use the cdll module.

Related

Call Windows Function in Python

https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntqueryinformationfile?redirectedfrom=MSDN
How can I call the above kernel method in python? I found an example on another stackoverflow post: Winapi: Get the process which has specific handle of a file
The answer on this other post is essentially what I want to do, but in python. The goal is to be able to get a list of processes which currently are accessing/locking a file. This NtQueryInformationFile method seems to be exactly what I want. I know this can be done with ctypes, but I am not familiar or comfortable enough with ctypes to do this myself. How can I do this?
If there's no available wrapper for the function, you'll need to call the function yourself using ctypes.
The dlls windows uses are exposed through ctypes.windll, with cytpes.windll.ntdll being the one that exposes the function you need.
To help python convert arguments, it's usually a good idea to specify the function's argument and return types, which can be done through the argtypes and restype attributes on the function object, like so:
function = cytpes.windll.ntdll.NtQueryInformationFile
function.argtypes = [ctypes.wintypes.HANDLE, ...]
function.restype = ctypes.c_long
ctypes exposes the common window types in the ctypes.wintypes module, though for most structures like the PIO_STATUS_BLOCK in your function you'll need to define the struct yourself and add it to the argument list to use it properly. In case it's optional a void pointer and passing it None will suffice.
Also, do mind that windows handles are not the file descriptors that python exposes, to convert to/from them you can use the ..._osfhandle functions from the msvcrt module

Passing argument for delphi functions loaded through ctype module from a dynamic link libraries(char pointer, DWORD handle)

while trying to control an external device through USB COM with python, I encountered followings problem: The actual function, written in an DLL in Delphi and loaded into python using ctypes module look like this:
function DmxProOpen (cSerNo: pchar; var dHandle: DWORD): integer;
stdcall; external 'DmxPro.dll';
This require as argument a character pointer and a 32 bit int pointer. So in Python i wrote this:
SerNo = 'EN096445' #actual serial number
SerNo = ctypes.c_char_p
dLocalHandle = POINTER(c_uint32) #Local handle to pass onto the function
DLLIMPORT.DmxProOpen.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint32)]
DLLIMPORT.DmxProOpen(SerNo, dLocalHandle)
which generates following error:
argument 1: <class 'TypeError'>: wrong type
Even though i see the type match that of the requirements. So the question is: how can I pass the Serial number which was given as 'EN096445' onto the function when it requires a 8 bit pointer? I have tried to explicitly make the SerNo variable a real pointer by using pointer() with a variable that stores the characters but that also generate the error:
SERNO = ctypes.pointer(SerNo)
TypeError: _type_ must have storage info
it also did not work with the method byref(). I also want to ask if there is a way to declare that the argument of a from DLL imported functions is by reference with the method argtypes from ctypes. I really appreciate any help. Thanks in advance and have a really nice day!

python ctypes sending pointer to structure as parameter to native library

I am trying to write a wrapper to a native library in Linux. Problem is this:
definition in c:
int mymethod(mystruct* ptr)
in python:
_lib.mymethod.argtypes = (ctypes.POINTER(mystruct),)
_lib.mymethod.restype = ctypes.c_int
s = mystruct()
_lib.mymethod(ctypes.byref(s))
# raises: expected LP_mystruct instance instead of pointer to mystruct
_lib.mymethod(ctypes.pointer(s))
# raises expected LP_mystruct instance instead of LP_mystruct
errors. How to pass a structure as a pointer to a native method ?
Thanks.
Mete
The problem is that the higher level "POINTER" from ctypes is, in Python, a different object than "a generic pointer" (ctypes.CArgObject by ctypes.byref)which is returned or a single number representing a memory address (which is what is returned by ctype's adrresof) - you can either annotate your function to receive a `ctypes.c_voidp and call it with _lib.mymethod(ctypes.addressof(a)) instead -
Or if you want to work on the stronged-typed side to avoid errors that would crash Python (a type error raises a Python exception instead - a wrong parameter passed to a C unction would cause a segmentation fault on the Python interpreter itself), you have to create a variable to hold the new "type" which is a POINTER to your structure - and then create an instance of this type with the address of your structure:
mystruct_pointer = ctypes.POINTER(mystruct)
_lib.mymethod.argtypes = (mystruct_pointer,)
_lib.mymethod.restype = ctypes.c_int
s = mystruct()
_lib.mymethod(mystruct_pointer.from_address(ctypes.addressof(s)))
(I know that this is an old question, but I think the accepted answer is an unnecessary workaround, so I want to leave this here for posterity.)
Actually ctypes should explicitly support using byref() to pass a pointer like that:
ctypes exports the byref() function which is used to pass parameters by reference. The same effect can be achieved with the pointer() function, although pointer() does a lot more work since it constructs a real pointer object, so it is faster to use byref() if you don’t need the pointer object in Python itself.
The likely cause of this is that you have defined your struct in more than one place (e.g. in different modules) - if the argtypes assignment sees one definition and the function call sees the other, this confusing error arises. In other words, ctypes tries to match two mystruct types that are (probably) identical in contents, and have the exact same name, but they are not the same type. As long as the base struct type is a single type object, it doesn't matter if you construct a pointer to it using pointer(), byref() or POINTER()() - ctypes will detect that the underlying (pointed-to) type is the same.
To verify if this is the case, try assert(_lib.mymethod.argtypes[0]._type_ == type(s)) right before calling the external function.

How can I use a DLL from Python

I am trying to load a DLL in Python, I want to use its eConnect() function using ctypes
What I know from the source code of the DLL:
from the *.cpp source code: bool eConnect( const char *host, UINT port, int clientId=0);
from the dependency walker tool: function ordinal is 6 and undecorated name is
?eConnect#EClientSocket##UAE_NPBDIH#Z
I tried to access the eConnect from two ways myfunction and myfunction2, but I probably get it wrong. Here is my code:
from ctypes import *
def main():
IP = c_char_p('127.0.0.1')
port = c_uint(7496)
client_id = c_int(0)
myfunction = getattr(cdll.TwsSocketClient, "?eConnect#EClientSocket##UAE_NPBDIH#Z")
myfunction2= cdll.TwsSocketClient[6]
print myfunction
print myfunction2
print myfunction(IP, port, client_id,IP)
if __name__ == "__main__":
main()
I get the below error:
"WindowsError: exception: access violation reading 0x0000002D"
I would badly need some help here (I do not know c++).
Thanks!
To make things easier, more Pythonic, you might want to look into ctypesgen:
http://code.google.com/p/ctypesgen/
It will generate proper wrapper functions, data types and such for you. If you just want to know how to use ctypes, might as well start with the tutorial:
http://docs.python.org/library/ctypes.html
Anything more specific and I'll have to read the API for the DLL you're attempting to use.
The function being exported is a class member function of the class EClientSocket. You're attempting to call that function from Python without passing in an EClientSocket pointer as the this parameter; furthermore, ctypes doesn't know anything about the __thiscall calling convention, so even if you did pass in an EClientSocket instance, it would be on the stack instead of in the ECX register.
The only real solution to this would be to export a C wrapper from your DLL that forwards the call to eConnect. For example:
extern "C" DLLEXPORT
bool EClientSocket_eConnect(EClientSocket *This, const char *host, UINT port, int clientId)
{
return This->eConnect(host, port, clientId);
}
However, even in that case, you have to be extra-careful on the Python side to construct an appropriate EClientSocket instance. I'd strongly recommend reconsidering your approach here.
Consider looking into IronPython. It makes it easier to call on DLL files.
There is also Boost::Python
Thanks for your answers everyone. I took Adam's advise and reconsidered my approached. As I do not know know c++, it was a bad idea from the start.
There is an alternative API in R (not official) which is built on top of the official Java API. It is then quite easy to link R and Python using rPy2.

Boost.Python function pointers as class constructor argument

I have a C++ class that requires a function pointer in it's constructor (float(*myfunction)(vector<float>*))
I've already exposed some function pointers to Python.
The ideal way to use this class is something like this:
import mymodule
mymodule.some_class(mymodule.some_function)
So I tell Boost about this class like so:
class_<SomeClass>("some_class", init<float(*)(vector<float>*)>);
But I get:
error: no matching function for call to 'register_shared_ptr1(Sample (*)(std::vector<double, std::allocator<double> >*))'
when I try to compile it.
So, does anyone have any ideas on how I can fix the error without losing the flexibility gained from function pointers (ie no falling back to strings that indicate which function to call)?
Also, the main point of writing this code in C++ is for speed. So it would be nice if I was still able to keep that benefit (the function pointer gets assigned to a member variable during initialization and will get called over a million times later on).
OK, so this is a fairly difficult question to answer in general. The root cause of your problem is that there really is no python type which is exactly equivalent to a C function pointer. Python functions are sort-of close, but their interface doesn't match for a few reasons.
Firstly, I want to mention the technique for wrapping a constructor from here:
http://wiki.python.org/moin/boost.python/HowTo#namedconstructors.2BAC8factories.28asPythoninitializers.29. This lets you write an __init__ function for your object that doesn't directly correspond to an actual C++ constructor. Note also, that you might have to specify boost::python::no_init in the boost::python::class_ construction, and then def a real __init__ function later, if your object isn't default-constructible.
Back to the question:
Is there only a small set of functions that you'll usually want to pass in? In that case, you could just declare a special enum (or specialized class), make an overload of your constructor that accepts the enum, and use that to look up the real function pointer. You can't directly call the functions yourself from python using this approach, but it's not that bad, and the performance will be the same as using real function pointers.
If you want to provide a general approach that will work for any python callable, things get more complex. You'll have to add a constructor to your C++ object that accepts a general functor, e.g. using boost::function or std::tr1::function. You could replace the existing constructor if you wanted, because function pointers will convert to this type correctly.
So, assuming you've added a boost::function constructor to SomeClass, you should add these functions to your python wrapping code:
struct WrapPythonCallable
{
typedef float * result_type;
explicit WrapPythonCallable(const boost::python::object & wrapped)
: wrapped_(wrapped)
{ }
float * operator()(vector<float>* arg) const
{
//Do whatever you need to do to convert into a
//boost::python::object here
boost::python::object arg_as_python_object = /* ... */;
//Call out to python with the object - note that wrapped_
//is callable using an operator() overload, and returns
//a boost::python::object.
//Also, the call can throw boost::python::error_already_set -
//you might want to handle that here.
boost::python::object result_object = wrapped_(arg_as_python_object);
//Do whatever you need to do to extract a float * from result_object,
//maybe using boost::python::extract
float * result = /* ... */;
return result;
}
boost::python::object wrapped_;
};
//This function is the "constructor wrapper" that you'll add to SomeClass.
//Change the return type to match the holder type for SomeClass, like if it's
//held using a shared_ptr.
std::auto_ptr<SomeClass> CreateSomeClassFromPython(
const boost::python::object & callable)
{
return std::auto_ptr<SomeClass>(
new SomeClass(WrapPythonCallable(callable)));
}
//Later, when telling Boost.Python about SomeClass:
class_<SomeClass>("some_class", no_init)
.def("__init__", make_constructor(&CreateSomeClassFromPython));
I've left out details on how to convert pointers to and from python - that's obviously something that you'll have to work out, because there are object lifetime issues there.
If you need to call the function pointers that you'll pass in to this function from Python, then you'll need to def these functions using Boost.Python at some point. This second approach will work fine with these def'd functions, but calling them will be slow, because objects will be unnecessarily converted to and from Python every time they're called.
To fix this, you can modify CreateSomeClassFromPython to recognize known or common function objects, and replace them with their real function pointers. You can compare python objects' identity in C++ using object1.ptr() == object2.ptr(), equivalent to id(object1) == id(object2) in python.
Finally, you can of course combine the general approach with the enum approach. Be aware when doing this, that boost::python's overloading rules are different from C++'s, and this can bite you when dealing with functions like CreateSomeClassFromPython. Boost.Python tests functions in the order that they are def'd to see if the runtime arguments can be converted to the C++ argument types. So, CreateSomeClassFromPython will prevent single-argument constructors def'd later than it from being used, because its argument matches any python object. Be sure to put it after other single-argument __init__ functions.
If you find yourself doing this sort of thing a lot, then you might want to look at the general boost::function wrapping technique (mentioned on the same page with the named constructor technique): http://wiki.python.org/moin/boost.python/HowTo?action=AttachFile&do=view&target=py_boost_function.hpp.

Categories

Resources