4
votes

Having some problems using ctypes

I have a testdll with following interface

extern "C"
{
    // Returns a + b
    double Add(double a, double b);
    // Returns a - b
    double Subtract(double a, double b);
    // Returns a * b
    double Multiply(double a, double b);
    // Returns a / b
    double Divide(double a, double b);
}

I also have a .def file so i have "real" names

LIBRARY "MathFuncsDll"
EXPORTS

 Add
 Subtract
 Multiply
 Divide

I can load and access the function from the dll via ctype but I cannot pass the parameter, see python output

>>> from ctypes import *
>>> x=windll.MathFuncsDll
>>> x
<WinDLL 'MathFuncsDll', handle 560000 at 29e1710>
>>> a=c_double(2.12)
>>> b=c_double(3.4432)
>>> x.Add(a,b)

Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    x.Add(a,b)
ValueError: Procedure probably called with too many arguments (16 bytes in excess)
>>> 

But I can the Function Add without parameters?!?!?!?!

>>> x.Add()
2619260

Can somebody point me in the right direction? I think forget something obvious because I can call function from other dll (eg. kernel32)

1
A few suggestions: (1) Try adding x.Add.restype = c_double (and similar) in order for your functions to return anything other than an int - see docs.python.org/library/ctypes.html#return-types. (2) Have you tried specifying the types of the function arguments (docs.python.org/library/…)? (3) Are you loading a 32-bit DLL on 64-bit Python, or a 64-bit DLL on 32-bit Python?Luke Woodward

1 Answers

8
votes

ctypes assumes int and pointer types for parameters and int for return values unless you specify otherwise. Exported functions also typically default to the C calling convention (CDLL in ctypes), not WinDLL. Try this:

from ctypes import *
x = CDLL('MathFuncsDll')
add = x.Add
add.restype = c_double
add.argtypes = [c_double,c_double]
print add(1.0,2.5)

Output

3.5