Reputation: 1
A have code in my dll (on C++). The function must accept a pointer to long
as an output variable:
int add(int a, long *ddd)
{
*ddd = 1758;
return a;
}
I am using Python 3:
from ctypes import *
import os
adr = os.getcwd()
dll = CDLL(adr + '\mydllcode.dll')
myint = 999
mylong = c_long(8888)
p_myint = c_int(myint)
p_mychar = c_wchar_p(mychar)
p_mylong = POINTER(mylong)
dll.add.argtypes = [c_int, POINTER(c_long)]
ret = dll.sub(p_myint, p_mylong)
print(ret)
print(str(mylong) + ' - ' + p_mylong.value)
And I get the error:
Traceback (most recent call last):
File "C:\PythonProjects\Shield\testdll.py", line 12, in <module>
p_mylong = POINTER(mylong)
TypeError: unhashable type
Upvotes: 0
Views: 905
Reputation: 177675
POINTER(ctypes-type)
declares a pointer type and its parameter must be a ctypes
type, so below was incorrect:
mylong = c_long(8888) # Creates a ctypes instance, not a type.
p_mylong = POINTER(mylong) # error
When you create a ctype to hold the output parameter, simply create an instance of the type:
mylong = c_long() # defaults to a value of zero, but for output parameter doesn't matter
Then pass it as a parameter by reference with:
byref(mylong)
Also, wrapping input values is generally unncessary if you set .argtypes
. ctypes
knows to wrap Python values as declared, so you can just pass them directly.
Example:
test.c
__declspec(dllexport)
int add(int a, long *ddd)
{
*ddd = 1758;
return a;
}
test.py
import ctypes as ct
dll = ct.CDLL('./test') # look in current directory for DLL.
dll.add.argtypes = ct.c_int,ct.POINTER(ct.c_long)
dll.add.restype = ct.c_int
mylong = ct.c_long() # instance to store output variable
ret = dll.add(999,ct.byref(mylong)) # pass by reference
print(ret,mylong.value) # .value extracts the result as a Python object.
Output:
999 1758
You can create pointers directly with pointer(instance
) as well, so below also works, but is less efficient than byref
:
import ctypes as ct
dll = ct.CDLL('./test')
dll.add.argtypes = ct.c_int,ct.POINTER(ct.c_long) # pointer type. Note upper case!
dll.add.restype = ct.c_int
mylong = ct.c_long() # create ctypes instance
p_mylong = ct.pointer(mylong) # create pointer to instance. Note lower case!
ret = dll.add(999,p_mylong)
print(ret,mylong.value)
Upvotes: 1
Reputation: 2696
I modified your code a little to Change the definitions to match. Following the ideas in the answer to Passing pointers to DLL function in Python , this may help
from ctypes import *
import os
adr = os.getcwd()
dll = CDLL(adr + '\mydllcode.dll')
myint = 999
mylong = c_long(8888)
p_myint = c_int(myint)
p_mychar = c_wchar_p(mychar)
p_mylong_p = ctypes.POINTER(ctypes.c_long)
dll.add.argtypes = [c_int, p_mylong_p]
ret = dll.sub(p_myint, ctypes.byref(mylong))
print(ret)
print(str(mylong) + ' - ' + p_mylong.value)
Upvotes: 0