3

so far I've gotten a DLL that wasn't meant for python to work with it, and types return: I just can't pass it arguments because I'm doing it wrong and I don't quite understand the documentation on how I'm supposed to do things. Basically, the function in the DLL I'm testing is named "iptouint". It takes a c_char_p and returns a c_double.

Here is my code:

nDll = ctypes.WinDLL('ndll.dll') nDllProto = ctypes.WINFUNCTYPE(ctypes.c_double) nDllInit = nDllProto(("dllInit", nDll)) nDllTestProto = ctypes.WINFUNCTYPE(ctypes.c_double,ctypes.c_char_p) nDllTest = nDllTestProto(("iptouint",nDll),((1, "p1",0),(1, "p2",0))) #This is the line that throws the error: print("IP: %s" % nDllTest("12.345.67.890")) ''' It gives me the error: ValueError: paramflags must have the same length as argtypes Im not sure what to do; Ive certainly played around with it to no avail. Help is much appreciated. Thanks. ''' 
2
  • Please,state the name and the C documentation for the function you are actuallyt rying to call inside the "ndll" dll. Commented Mar 6, 2011 at 1:26
  • @jsbueno Like I said, the function is named "iptouint" and takes a double and returns a string. Commented Mar 6, 2011 at 1:35

1 Answer 1

2

try simply indicating ctypes the argtypes it takes and the ones it returns:

nDll = ctypes.WinDLL('ndll.dll') nDll.restype = ctypes.c_double nDll.argtypes = [ctypes.c_char_p] result = nDll.iptouint("12.345.67.890").value 

Although, consider these points:

1) if, as the name indicates, this converts an IPv4 value s ina string to an Unsigned Int, the return type os not "double" as you say - it would be ctypes.c_uint32

2) Your example value is not a valit IPv4 address, and cannot be converted to a 32 bit integer (neither does it makes sense as a "double" - i.e. a 64 bit floating point number) - it is simply invalid

3) You don't need that if you are just trying to have an unsigned 32bit value for an ipv4 address in Python. There are quite a few, very readable, easier, and multiplatform ways to do that with pure python. For example:

def iptoint(ip): value = 0 for component in ip.split("."): value <<= 8 #shifts previous value 8 bits to the left, #leaving space for the next byte value |= int(component) # sets the bits for the new byte in the address return value 

update: In Python 3.x there is the ipaddress module - https://docs.python.org/3/library/ipaddress.html - which is also available as a pip install for Python 2.x - it can handle this always in the correct way, and works fine with IPv6 as well.

Sign up to request clarification or add additional context in comments.

3 Comments

Yes - I had my IP in the slot and I simply covered it up. In addition, the DLL this was meant for only deals with strings and doubles. Once it's inside python it doesn't really make a difference. Also, this was only one function. The DLL is actually a networking one that I find very usefull because it can read from a very unique message that I need to read from. Thank you for your response. :) I will try what you suggested.
Wait - This code seems to only work well with a DLL that only has one function. Mine has many... is there any way I can keep it this easy and use all of the functions in the DLL?
You have to decaroate each function you will use so that cpython gets to known which parameters to send and to receive back. Otherwise, it just tries educated guesses - like "int" for any number, and "char_p" for anuy string you pass as a parameter (but it will assume the function returns an int anyway). Just set the argtypes and restype for each function you will use.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.