2

I'm using Python and ctypes to use a .dll supplied by a company for the use with a load cell amplifier. I manage to get a reading with their software, but I can't get my Python code to work. The company is ME-MessSysteme, and the amplifier is the GSV-2 (Manual Here).

The company's description of the function:

C: int GSVread ( int no, double *ad )

Taken from here, page 44. Sorry, but the guide is in German.

I'm getting a response from the amplifier after the activate function, but when I use the GSVread function, I can't get the result. I tried to pass a pointer to a double variable as I understand it returns the value to it. When I try to access the contents I get a "ValueError: NULL pointer access".

import ctypes
ret = ctypes.POINTER(ctypes.c_double)()
print(ret)
gsv = ctypes.cdll.LoadLibrary("DLLs_SENSOLYTICS/MEGSV.dll")
print(gsv.GSVactivate(7))
print(gsv.GSVstartTransmit(7))
print(gsv.GSVread(7, ret))
print(ret.contents)

7 indicating the COM port number.

Thank you all in advance!

****UPDATE***** Following on Dan's answer, the code that works is below:

    d = ctypes.c_double()
    ret = ctypes.byref(d)

    gsv = ctypes.cdll.LoadLibrary("DLLs_SENSOLYTICS/MEGSV.dll")
    print(gsv.GSVactivate(7, ctypes.c_long(256)))
    gsv.GSVflushBuffer(7)
    print(gsv.GSVstartTransmit(7))
    time.sleep(1)
    gsv.GSVread(7, ret)
    print(d)
1
  • Typically, just do d = ctypes.c_double(), then gsv.GSVread(7,ctypes.byref(d)). That passes the address of d to the function, and d.value will be the result when the function returns. It's also a good habit to explicitly define .argtypes and .restype for each function so ctypes can perform type checking and properly marshal the arguments to the C function. Commented Dec 19, 2019 at 8:41

1 Answer 1

2

You need to create two objects one the double and the other the pointer to the double:

>>> d = ctypes.c_double()
>>> ret = ctypes.pointer(d)
>>> ret.contents
c_double(0.0)

This can also be written as:

ret = ctypes.pointer(ctypes.c_double())

Which is oddly similar to:

ret = ctypes.POINTER(ctypes.c_double)()

The documentation states that ctypes.byref is a faster ctypes.pointer that doesn't actually allocate a real ctypes.pointer object so it can only be used to be be passed to a reference as an argument to a C function.

To use it one has to keep a direct reference to the double to be able to access the result as ctypes.byref objects do not have a contents property.

d = ctypes.c_double()
ret = ctypes.byref(d)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! This indeed works, and I would like to add that it also took to add a waiting period. The new code is updated in the question.

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.