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 c开发者_开发百科types 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.
精彩评论