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)