3

I am currently working on a project that requires to access functions in DLLs, and I found ctypes to handle the function call for me. However, I encounter some difficulties when some functions ask to pass parameters by reference. I've tried the ctypes.by_ref() but it doesn't work because the object is a user-defined class.

And then I gave ctypes.pointer() a try and it spits out the error message: "type must have storage info". I guess that means it only takes ctypes data types?

My code:

from ctypes import *
class myclass():
    a= None # requiring c_int32
    b= None # requiring c_int32
myci= myclass()
myci.a= c_int32(255)
myci.b= c_int32(0)
mycip= pointer(myci)  # let's say it's Line 8 here
loadso= cdll.LoadLibrary(mydll)
Result= loadso.thefunction (mycip) # int thefunction(ref myclass)

And the terminal output:

Line 8: TypeError: _type_ must have storage info

I would like to know 1) what does that error message mean? and 2) the way to work around and pass a user-defined class by reference to an external DLL.

Thank you in advance for your time.

  • *ctypes* comes from **_C_** types (which typically can't handle *C++* types). However without seeing some code ([\[SO\]: How to create a Minimal, Complete, and Verifiable example (mcve)](https://stackoverflow.com/help/mcve)), it's hard to guess the error (and the fix). – CristiFati Jun 12 '18 at 14:43
  • @CristiFati at first I thought this question could be asked without presenting some codes because it's more about methodology and asking for the meaning of a specific error message. But I would add some code in the next edit to make things clearer. – nakamurayuristeph Jun 12 '18 at 14:46
  • That's not the way of using *ctypes*. Check https://docs.python.org/3/library/ctypes.html#module-ctypes. Also *Google* yields tons of examples.https://stackoverflow.com/questions/50447199/ctypes-struct-containing-arrays, https://stackoverflow.com/questions/50325050/ctypes-argumenterror-when-calling-dll-functions-with-python, https://stackoverflow.com/questions/50003760/python-ctypes-calling-a-function-with-custom-types-in-c, https://stackoverflow.com/questions/49962265/c-to-python-via-ctypes-wrapping-struct-of-function-pointers-to-static-function, are just a few of mine... – CristiFati Jun 12 '18 at 16:10
  • @CristiFati Can you elaborate on why it's not how we use ctypes? Is the use case not appropriate? Or wrong setups maybe? I've read all of the articles linked above, does it mean that there is no way around but to inherit myclass under Structure? The reason I didn't inherit under Structure is that CPython doesn't differentiate c_int and c_long, depending on the machine architecture, and that CPython store field values(c_int16, c_int32, no matter what it is required) in int. And I just don't like that behavior. But if using a Structure is the best way I 'll do it. – nakamurayuristeph Jun 12 '18 at 17:09

1 Answers1

3

The error message means that you can't create a ctypes pointer to a non-ctypes type. ctypes types have the information needed to marshal values correctly to C.

Read ctypes: Structures and Unions. The first sentence is (emphasis mine):

Structures and unions must derive from the Structure and Union base classes which are defined in the ctypes module.

For example:

>>> from ctypes import *
>>> class Test(Structure):
...   _fields_ = [('a',c_int32),
...               ('b',c_int16),
...               ('c',c_int16)]
...
>>> t = Test(1,2,3)
>>> pointer(t)
<__main__.LP_Test object at 0x00000234A8750A48>
>>> bytes(t)
b'\x01\x00\x00\x00\x02\x00\x03\x00'

Note that a pointer can be taken and that the raw bytes of the structure can be displayed. The structure is little-endian and there are four bytes allocated for the c_int32, and two bytes each for the two c_int16 members.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251