How can I use a DLL from Python - 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.

Related

Return a 3rd party pybind type

My C++ library depends on a 3rd party C++ library with its own bindings.
I bind a struct that uses def_readwrite to expose its members. One of its members is a type from the 3rd party library.
Basically I have:
struct MyStruct {
ClassFromThirdParty member{};
}
py::class_<MyStruct>(m, "MyStruct")
.def_readwrite("member", &MyStruct::member)
In Python I try:
from my_bindings import MyStruct
obj = MyStruct()
print(obj.member)
but this raises TypeError: Unable to convert function return value to a Python type!.
It's worth also noting that if I do:
import ThirdPartyLibrary
from my_bindings import MyStruct
obj = MyStruct()
print(obj.member)
no error is raised. But I don't like this solution as the Python user would have to import ThirdPartyLibrary even if they don't explicitly need it.
How do I write my binding such that the first Python snippet works?
PS: The third party binding in question can be found here. In the absence of a general answer, I'd also be happy to hear answers related to that library in particular.
It's the same in pybind11 as it is in Python -- you need to import classes before you can rely on them.
Add py::module::import("pydrake.math"); to your PYBIND11_MODULE before trying to define function bindings that operate on a pydrake.math.RigidTransform as a C++ argument type or C++ return value type.

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

how to include shared object in python [duplicate]

I'm just getting started with ctypes and would like to use a C++ class that I have exported in a dll file from within python using ctypes.
So lets say my C++ code looks something like this:
class MyClass {
public:
int test();
...
I would know create a .dll file that contains this class and then load the .dll file in python using ctypes.
Now how would I create an Object of type MyClass and call its test function? Is that even possible with ctypes? Alternatively I would consider using SWIG or Boost.Python but ctypes seems like the easiest option for small projects.
Besides Boost.Python(which is probably a more friendly solution for larger projects that require one-to-one mapping of C++ classes to python classes), you could provide on the C++ side a C interface. It's one solution of many so it has its own trade offs, but I will present it for the benefit of those who aren't familiar with the technique. For full disclosure, with this approach one wouldn't be interfacing C++ to python, but C++ to C to Python. Below I included an example that meets your requirements to show you the general idea of the extern "c" facility of C++ compilers.
//YourFile.cpp (compiled into a .dll or .so file)
#include <new> //For std::nothrow
//Either include a header defining your class, or define it here.
extern "C" //Tells the compile to use C-linkage for the next scope.
{
//Note: The interface this linkage region needs to use C only.
void * CreateInstanceOfClass( void )
{
// Note: Inside the function body, I can use C++.
return new(std::nothrow) MyClass;
}
//Thanks Chris.
void DeleteInstanceOfClass (void *ptr)
{
delete(std::nothrow) ptr;
}
int CallMemberTest(void *ptr)
{
// Note: A downside here is the lack of type safety.
// You could always internally(in the C++ library) save a reference to all
// pointers created of type MyClass and verify it is an element in that
//structure.
//
// Per comments with Andre, we should avoid throwing exceptions.
try
{
MyClass * ref = reinterpret_cast<MyClass *>(ptr);
return ref->Test();
}
catch(...)
{
return -1; //assuming -1 is an error condition.
}
}
} //End C linkage scope.
You can compile this code with
gcc -shared -o test.so test.cpp
#creates test.so in your current working directory.
In your python code you could do something like this (interactive prompt from 2.7 shown):
>>> from ctypes import cdll
>>> stdc=cdll.LoadLibrary("libc.so.6") # or similar to load c library
>>> stdcpp=cdll.LoadLibrary("libstdc++.so.6") # or similar to load c++ library
>>> myLib=cdll.LoadLibrary("/path/to/test.so")
>>> spam = myLib.CreateInstanceOfClass()
>>> spam
[outputs the pointer address of the element]
>>> value=CallMemberTest(spam)
[does whatever Test does to the spam reference of the object]
I'm sure Boost.Python does something similar under the hood, but perhaps understanding the lower levels concepts is helpful. I would be more excited about this method if you were attempting to access functionality of a C++ library and a one-to-one mapping was not required.
For more information on C/C++ interaction check out this page from Sun: http://dsc.sun.com/solaris/articles/mixing.html#cpp_from_c
The short story is that there is no standard binary interface for C++ in the way that there is for C. Different compilers output different binaries for the same C++ dynamic libraries, due to name mangling and different ways to handle the stack between library function calls.
So, unfortunately, there really isn't a portable way to access C++ libraries in general. But, for one compiler at a time, it's no problem.
This blog post also has a short overview of why this currently won't work. Maybe after C++0x comes out, we'll have a standard ABI for C++? Until then, you're probably not going to have any way to access C++ classes through Python's ctypes.
The answer by AudaAero is very good but not complete (at least for me).
On my system (Debian Stretch x64 with GCC and G++ 6.3.0, Python 3.5.3) I have segfaults as soon has I call a member function that access a member value of the class.
I diagnosticated by printing pointer values to stdout that the void* pointer coded on 64 bits in wrappers is being represented on 32 bits in Python. Thus big problems occurs when it is passed back to a member function wrapper.
The solution I found is to change:
spam = myLib.CreateInstanceOfClass()
Into
Class_ctor_wrapper = myLib.CreateInstanceOfClass
Class_ctor_wrapper.restype = c_void_p
spam = c_void_p(Class_ctor_wrapper())
So two things were missing: setting the return type to c_void_p (the default is int) and then creating a c_void_p object (not just an integer).
I wish I could have written a comment but I still lack 27 rep points.
Extending AudaAero's and Gabriel Devillers answer I would complete the class object instance creation by:
stdc=c_void_p(cdll.LoadLibrary("libc.so.6"))
using ctypes c_void_p data type ensures the proper representation of the class object pointer within python.
Also make sure that the dll's memory management be handled by the dll (allocated memory in the dll should be deallocated also in the dll, and not in python)!
I ran into the same problem. From trial and error and some internet research (not necessarily from knowing the g++ compiler or C++ very well), I came across this particular solution that seems to be working quite well for me.
//model.hpp
class Model{
public:
static Model* CreateModel(char* model_name) asm("CreateModel"); // static method, creates an instance of the class
double GetValue(uint32_t index) asm("GetValue"); // object method
}
#model.py
from ctypes import ...
if __name__ == '__main__':
# load dll as model_dll
# Static Method Signature
fCreateModel = getattr(model_dll, 'CreateModel') # or model_dll.CreateModel
fCreateModel.argtypes = [c_char_p]
fCreateModel.restype = c_void_p
# Object Method Signature
fGetValue = getattr(model_dll, 'GetValue') # or model_dll.GetValue
fGetValue.argtypes = [c_void_p, c_uint32] # Notice two Params
fGetValue.restype = c_double
# Calling the Methods
obj_ptr = fCreateModel(c_char_p(b"new_model"))
val = fGetValue(obj_ptr, c_int32(0)) # pass in obj_ptr as first param of obj method
>>> nm -Dg libmodel.so
U cbrt#GLIBC_2.2.5
U close#GLIBC_2.2.5
00000000000033a0 T CreateModel # <----- Static Method
U __cxa_atexit#GLIBC_2.2.5
w __cxa_finalize#GLIBC_2.2.5
U fprintf#GLIBC_2.2.5
0000000000002b40 T GetValue # <----- Object Method
w __gmon_start__
...
...
... # Mangled Symbol Names Below
0000000000002430 T _ZN12SHMEMWrapper4HashEPKc
0000000000006120 B _ZN12SHMEMWrapper8info_mapE
00000000000033f0 T _ZN5Model12DestroyModelEPKc
0000000000002b20 T _ZN5Model14GetLinearIndexElll
First, I was able to avoid the extern "C" directive completely by instead using the asm keyword which, to my knowledge, asks the compiler to use a given name instead of the generated one when exporting the function to the shared object lib's symbol table. This allowed me to avoid the weird symbol names that the C++ compiler generates automatically. They look something like the _ZN1... pattern you see above. Then in a program using Python ctypes, I was able to access the class functions directly using the custom name I gave them. The program looks like fhandle = mydll.myfunc or fhandler = getattr(mydll, 'myfunc') instead of fhandle = getattr(mydll, '_ZN12...myfunc...'). Of course, you could just use the long name; it would make no difference, but I figure the shorter name is a little cleaner and doesn't require using nm to read the symbol table and extract the names in the first place.
Second, in the spirit of Python's style of object oriented programming, I decided to try passing in my class' object pointer as the first argument of the class object method, just like when we pass self in as the first method in Python object methods. To my surprise, it worked! See the Python section above. Apparently, if you set the first argument in the fhandle.argtypes argument to c_void_ptr and pass in the ptr you get from your class' static factory method, the program should execute cleanly. Class static methods seem to work as one would expect like in Python; just use the original function signature.
I'm using g++ 12.1.1, python 3.10.5 on Arch Linux. I hope this helps someone.

Passing structure with pointers to other structures in ctypes

I am trying to make a python wrapper for a C library using ctypes. The library has functions which require a pointer to a structure to be passed, which acts as a handle for future calls.
This structure has pointers to another internal structure that further has pointers to other structures.
typedef struct varnam {
char *scheme_file;
char *suggestions_file;
struct varnam_internal *internal;
} varnam;
The varnam_internal structure has pointers to an sqlite database and so forth
struct varnam_internal
{
sqlite3 *db;
sqlite3 *known_words;
struct varray_t *r;
struct token *v;
...
}
I tried ignoring the varnam_internal structure according to this SO answer. Something like
class Varnam(Structure):
__fields__ = [("scheme_file",c_char_p),
("suggestions_file",c_char_p),("internal",c_void_p)]
But this does not seem to work because I think the library needs to allocate varnam_internal for functioning properly.
Should I implement all the dependent structures in python? Is ctypes suitable for wrapping libraries like this? I have read about alternatives like Cython but I have no experience with Cython so is this doable in it?
There's no reason define the varnam_internal structure in ctypes because you should have no need to access it. The library you're calling will allocate it regardless of whether you define the structure or not. Whatever problem you're encountering it's not because you didn't define the structure in ctypes.
Make sure you're calling varnam_init correctly. It uses pointers to pointers as arguments, which means you can't just use your Varnam class directly. You'll want do something like this:
from ctypes import *
class Varnam(Structure):
__fields__ = [("scheme_file",c_char_p),
("suggestions_file",c_char_p),
("internal",c_void_p)]
varnam_ptr = POINTER(Varnam)
libvarnam = cdll.LoadLibrary("libvarnam.so") # on Linux
# libvarnam = cdll.libvarnam # on Windows
varnam_init = libvarnam.varnam_init
varnam_init.argtypes = [c_char_p, POINTER(varnam_ptr), POINTER(c_char_p)]
def my_varnam_init(scheme_file):
handle = varnam_ptr()
msg = c_char_p()
r = varnam_init(scheme_file. handle.byref(), msg.byref())
if r != 0:
raise Exception(msg)
return handle
The above code is completely untested, but shows you how you should be calling varnam_init.

Too many arguments in my function - 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.

Categories

Resources