0

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

2 Answers 2

1

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)
Sign up to request clarification or add additional context in comments.

Comments

0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.