Distinguish between “fundamental” ctypes data types and subclasses thereof?2019 Community Moderator ElectionGetting method parameter names in PythonWhat are the differences between type() and isinstance()?How to use C++ classes with ctypes?Receiving non Null-Terminated data in Python Ctypes callbackAdding data to a C buffer passed to a Python Ctypes callbackc_void_p arguments in callbacks using ctypes in PythonSubclassing ctypes typesPython 3.x ctype c_wchar_p and c_char_p return status different from ctypes docHow to create c_void_p PyObject from C++, pass it to Python and retrieve it back to C++Python ctypes : create user defined types and exchange with function in dll
DisplayForm problem with pi in FractionBox
Knife as defense against stray dogs
Pre-Employment Background Check With Consent For Future Checks
Did Nintendo change its mind about 68000 SNES?
When should a starting writer get his own webpage?
CLI: Get information Ubuntu releases
Do I need an EFI partition for each 18.04 ubuntu I have on my HD?
How to test the sharpness of a knife?
Single word to change groups
What kind of footwear is suitable for walking in micro gravity environment?
The English Debate
is this saw blade faulty?
Exposing a company lying about themselves in a tightly knit industry: Is my career at risk on the long run?
Was World War I a war of liberals against authoritarians?
Do people actually use the word "kaputt" in conversation?
Writing in a Christian voice
Exit shell with shortcut (not typing exit) that closes session properly
How to find the largest number(s) in a list of elements, possibly non-unique?
What is the tangent at a sharp point on a curve?
Friend wants my recommendation but I don't want to
Would mining huge amounts of resources on the Moon change its orbit?
Should I be concerned about student access to a test bank?
Turning a hard to access nut?
Have any astronauts/cosmonauts died in space?
Distinguish between “fundamental” ctypes data types and subclasses thereof?
2019 Community Moderator ElectionGetting method parameter names in PythonWhat are the differences between type() and isinstance()?How to use C++ classes with ctypes?Receiving non Null-Terminated data in Python Ctypes callbackAdding data to a C buffer passed to a Python Ctypes callbackc_void_p arguments in callbacks using ctypes in PythonSubclassing ctypes typesPython 3.x ctype c_wchar_p and c_char_p return status different from ctypes docHow to create c_void_p PyObject from C++, pass it to Python and retrieve it back to C++Python ctypes : create user defined types and exchange with function in dll
Introduction
I am working on a code generator that would generate functions around ctypes.cdll
loaded functions. The generator would take information about the ctypes
of the arguments and the return value, and generate something that behaves (and, to some extent, looks) like this:
func = getattr(dll, 'UglyLongAndUselessCName')
func.argtypes = [ctypes.c_uint32, ctypes.c_int8, ctypes.c_char_p]
func.restype = ctypes.c_int16
def nice_python_name(handle: int, arg1: int, arg2: str) -> int:
return func(handle, arg1, arg2)
Notice how python type annotations play nicely with the ctypes
data types of the function arguments. Also notice that there is no conversion code between the python types in nice_python_name
function and func
function. This is what my question is about.
Getting close to the problem
The ctypes
docs say that if the argtypes
attribute of a loaded DLL function is specified using "fundamental data types", then when calling the loaded DLL functions, ctypes
will do the conversion to python types for you. This is great, because in this case my generated code will look like the example above - I won't need to explicitly convert ctypes
objects to python-typed values for returned values, and the reverse for the arguments.
However, the docs also say that for "subclasses of the fundamental data types" this trick will not work, and calling a loaded DLL function will require ctypes
objects for arguments, and the result will be a ctypes
object.
This is the excerpt from the ctypes
docs about it:
Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a
restype
ofc_char_p
, you will always receive a Python bytes object, not ac_char_p
instance.
Subclasses of fundamental data types do not inherit this behavior. So, if a foreign functions
restype
is a subclass ofc_void_p
, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the value attribute.
So, I would like to get around this.
It seems that I need to know if a type is "fundamental" or a "subclass". This will help me define the way the code is generated, i.e. for "fundamental" types the generated code would look similar to the above example, and for "subclasses of fundamental" types it will have the extra conversion from ctypes
objects into reasonable python types (or the generator will just throw an exception saying "this is not supported").
Question:
How can I distinguish between "fundamental ctypes
data types" and "subclasses of fundamental ctypes
data types"?
I looked into the code of ctypes
python module and discovered that both c_void_p
and c_char_p
are subclasses of ctypes._SimpleCData
, hence one is not a subclass of the other in any way.
Also, do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
python parameter-passing ctypes dllimport
add a comment |
Introduction
I am working on a code generator that would generate functions around ctypes.cdll
loaded functions. The generator would take information about the ctypes
of the arguments and the return value, and generate something that behaves (and, to some extent, looks) like this:
func = getattr(dll, 'UglyLongAndUselessCName')
func.argtypes = [ctypes.c_uint32, ctypes.c_int8, ctypes.c_char_p]
func.restype = ctypes.c_int16
def nice_python_name(handle: int, arg1: int, arg2: str) -> int:
return func(handle, arg1, arg2)
Notice how python type annotations play nicely with the ctypes
data types of the function arguments. Also notice that there is no conversion code between the python types in nice_python_name
function and func
function. This is what my question is about.
Getting close to the problem
The ctypes
docs say that if the argtypes
attribute of a loaded DLL function is specified using "fundamental data types", then when calling the loaded DLL functions, ctypes
will do the conversion to python types for you. This is great, because in this case my generated code will look like the example above - I won't need to explicitly convert ctypes
objects to python-typed values for returned values, and the reverse for the arguments.
However, the docs also say that for "subclasses of the fundamental data types" this trick will not work, and calling a loaded DLL function will require ctypes
objects for arguments, and the result will be a ctypes
object.
This is the excerpt from the ctypes
docs about it:
Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a
restype
ofc_char_p
, you will always receive a Python bytes object, not ac_char_p
instance.
Subclasses of fundamental data types do not inherit this behavior. So, if a foreign functions
restype
is a subclass ofc_void_p
, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the value attribute.
So, I would like to get around this.
It seems that I need to know if a type is "fundamental" or a "subclass". This will help me define the way the code is generated, i.e. for "fundamental" types the generated code would look similar to the above example, and for "subclasses of fundamental" types it will have the extra conversion from ctypes
objects into reasonable python types (or the generator will just throw an exception saying "this is not supported").
Question:
How can I distinguish between "fundamental ctypes
data types" and "subclasses of fundamental ctypes
data types"?
I looked into the code of ctypes
python module and discovered that both c_void_p
and c_char_p
are subclasses of ctypes._SimpleCData
, hence one is not a subclass of the other in any way.
Also, do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
python parameter-passing ctypes dllimport
add a comment |
Introduction
I am working on a code generator that would generate functions around ctypes.cdll
loaded functions. The generator would take information about the ctypes
of the arguments and the return value, and generate something that behaves (and, to some extent, looks) like this:
func = getattr(dll, 'UglyLongAndUselessCName')
func.argtypes = [ctypes.c_uint32, ctypes.c_int8, ctypes.c_char_p]
func.restype = ctypes.c_int16
def nice_python_name(handle: int, arg1: int, arg2: str) -> int:
return func(handle, arg1, arg2)
Notice how python type annotations play nicely with the ctypes
data types of the function arguments. Also notice that there is no conversion code between the python types in nice_python_name
function and func
function. This is what my question is about.
Getting close to the problem
The ctypes
docs say that if the argtypes
attribute of a loaded DLL function is specified using "fundamental data types", then when calling the loaded DLL functions, ctypes
will do the conversion to python types for you. This is great, because in this case my generated code will look like the example above - I won't need to explicitly convert ctypes
objects to python-typed values for returned values, and the reverse for the arguments.
However, the docs also say that for "subclasses of the fundamental data types" this trick will not work, and calling a loaded DLL function will require ctypes
objects for arguments, and the result will be a ctypes
object.
This is the excerpt from the ctypes
docs about it:
Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a
restype
ofc_char_p
, you will always receive a Python bytes object, not ac_char_p
instance.
Subclasses of fundamental data types do not inherit this behavior. So, if a foreign functions
restype
is a subclass ofc_void_p
, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the value attribute.
So, I would like to get around this.
It seems that I need to know if a type is "fundamental" or a "subclass". This will help me define the way the code is generated, i.e. for "fundamental" types the generated code would look similar to the above example, and for "subclasses of fundamental" types it will have the extra conversion from ctypes
objects into reasonable python types (or the generator will just throw an exception saying "this is not supported").
Question:
How can I distinguish between "fundamental ctypes
data types" and "subclasses of fundamental ctypes
data types"?
I looked into the code of ctypes
python module and discovered that both c_void_p
and c_char_p
are subclasses of ctypes._SimpleCData
, hence one is not a subclass of the other in any way.
Also, do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
python parameter-passing ctypes dllimport
Introduction
I am working on a code generator that would generate functions around ctypes.cdll
loaded functions. The generator would take information about the ctypes
of the arguments and the return value, and generate something that behaves (and, to some extent, looks) like this:
func = getattr(dll, 'UglyLongAndUselessCName')
func.argtypes = [ctypes.c_uint32, ctypes.c_int8, ctypes.c_char_p]
func.restype = ctypes.c_int16
def nice_python_name(handle: int, arg1: int, arg2: str) -> int:
return func(handle, arg1, arg2)
Notice how python type annotations play nicely with the ctypes
data types of the function arguments. Also notice that there is no conversion code between the python types in nice_python_name
function and func
function. This is what my question is about.
Getting close to the problem
The ctypes
docs say that if the argtypes
attribute of a loaded DLL function is specified using "fundamental data types", then when calling the loaded DLL functions, ctypes
will do the conversion to python types for you. This is great, because in this case my generated code will look like the example above - I won't need to explicitly convert ctypes
objects to python-typed values for returned values, and the reverse for the arguments.
However, the docs also say that for "subclasses of the fundamental data types" this trick will not work, and calling a loaded DLL function will require ctypes
objects for arguments, and the result will be a ctypes
object.
This is the excerpt from the ctypes
docs about it:
Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a
restype
ofc_char_p
, you will always receive a Python bytes object, not ac_char_p
instance.
Subclasses of fundamental data types do not inherit this behavior. So, if a foreign functions
restype
is a subclass ofc_void_p
, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the value attribute.
So, I would like to get around this.
It seems that I need to know if a type is "fundamental" or a "subclass". This will help me define the way the code is generated, i.e. for "fundamental" types the generated code would look similar to the above example, and for "subclasses of fundamental" types it will have the extra conversion from ctypes
objects into reasonable python types (or the generator will just throw an exception saying "this is not supported").
Question:
How can I distinguish between "fundamental ctypes
data types" and "subclasses of fundamental ctypes
data types"?
I looked into the code of ctypes
python module and discovered that both c_void_p
and c_char_p
are subclasses of ctypes._SimpleCData
, hence one is not a subclass of the other in any way.
Also, do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
python parameter-passing ctypes dllimport
python parameter-passing ctypes dllimport
asked Mar 7 at 18:49
astafan8astafan8
6316
6316
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
... do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
It does not apply to input arguments, as the sequence below shows:
>>> dll=CDLL('msvcrt')
>>> dll.printf.argtypes = c_char_p,
>>> dll.printf(b'abc') # Note: 3 is the return value of printf
abc3
>>> class LPCSTR(c_char_p): # define a subtype
... pass
...
>>> dll.printf.argtypes = LPCSTR,
>>> dll.printf(b'abc')
abc3
Conversions still work for input subtypes; however, output subtypes work differently as your doc quote mentioned:
>>> dll.ctime.argtypes = c_void_p,
>>> dll.ctime.restype = c_char_p
>>> dll.ctime(byref(c_int(5)))
b'Wed Dec 31 16:00:05 1969n'
>>> dll.ctime.restype = LPCSTR
>>> dll.ctime(byref(c_int(5))) # not converted to Python byte string
LPCSTR(1989707373328)
>>> x = dll.ctime(byref(c_int(5))) # but can get the value
>>> x.value
b'Wed Dec 31 16:00:05 1969n'
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55050845%2fdistinguish-between-fundamental-ctypes-data-types-and-subclasses-thereof%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
... do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
It does not apply to input arguments, as the sequence below shows:
>>> dll=CDLL('msvcrt')
>>> dll.printf.argtypes = c_char_p,
>>> dll.printf(b'abc') # Note: 3 is the return value of printf
abc3
>>> class LPCSTR(c_char_p): # define a subtype
... pass
...
>>> dll.printf.argtypes = LPCSTR,
>>> dll.printf(b'abc')
abc3
Conversions still work for input subtypes; however, output subtypes work differently as your doc quote mentioned:
>>> dll.ctime.argtypes = c_void_p,
>>> dll.ctime.restype = c_char_p
>>> dll.ctime(byref(c_int(5)))
b'Wed Dec 31 16:00:05 1969n'
>>> dll.ctime.restype = LPCSTR
>>> dll.ctime(byref(c_int(5))) # not converted to Python byte string
LPCSTR(1989707373328)
>>> x = dll.ctime(byref(c_int(5))) # but can get the value
>>> x.value
b'Wed Dec 31 16:00:05 1969n'
add a comment |
... do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
It does not apply to input arguments, as the sequence below shows:
>>> dll=CDLL('msvcrt')
>>> dll.printf.argtypes = c_char_p,
>>> dll.printf(b'abc') # Note: 3 is the return value of printf
abc3
>>> class LPCSTR(c_char_p): # define a subtype
... pass
...
>>> dll.printf.argtypes = LPCSTR,
>>> dll.printf(b'abc')
abc3
Conversions still work for input subtypes; however, output subtypes work differently as your doc quote mentioned:
>>> dll.ctime.argtypes = c_void_p,
>>> dll.ctime.restype = c_char_p
>>> dll.ctime(byref(c_int(5)))
b'Wed Dec 31 16:00:05 1969n'
>>> dll.ctime.restype = LPCSTR
>>> dll.ctime(byref(c_int(5))) # not converted to Python byte string
LPCSTR(1989707373328)
>>> x = dll.ctime(byref(c_int(5))) # but can get the value
>>> x.value
b'Wed Dec 31 16:00:05 1969n'
add a comment |
... do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
It does not apply to input arguments, as the sequence below shows:
>>> dll=CDLL('msvcrt')
>>> dll.printf.argtypes = c_char_p,
>>> dll.printf(b'abc') # Note: 3 is the return value of printf
abc3
>>> class LPCSTR(c_char_p): # define a subtype
... pass
...
>>> dll.printf.argtypes = LPCSTR,
>>> dll.printf(b'abc')
abc3
Conversions still work for input subtypes; however, output subtypes work differently as your doc quote mentioned:
>>> dll.ctime.argtypes = c_void_p,
>>> dll.ctime.restype = c_char_p
>>> dll.ctime(byref(c_int(5)))
b'Wed Dec 31 16:00:05 1969n'
>>> dll.ctime.restype = LPCSTR
>>> dll.ctime(byref(c_int(5))) # not converted to Python byte string
LPCSTR(1989707373328)
>>> x = dll.ctime(byref(c_int(5))) # but can get the value
>>> x.value
b'Wed Dec 31 16:00:05 1969n'
... do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?
It does not apply to input arguments, as the sequence below shows:
>>> dll=CDLL('msvcrt')
>>> dll.printf.argtypes = c_char_p,
>>> dll.printf(b'abc') # Note: 3 is the return value of printf
abc3
>>> class LPCSTR(c_char_p): # define a subtype
... pass
...
>>> dll.printf.argtypes = LPCSTR,
>>> dll.printf(b'abc')
abc3
Conversions still work for input subtypes; however, output subtypes work differently as your doc quote mentioned:
>>> dll.ctime.argtypes = c_void_p,
>>> dll.ctime.restype = c_char_p
>>> dll.ctime(byref(c_int(5)))
b'Wed Dec 31 16:00:05 1969n'
>>> dll.ctime.restype = LPCSTR
>>> dll.ctime(byref(c_int(5))) # not converted to Python byte string
LPCSTR(1989707373328)
>>> x = dll.ctime(byref(c_int(5))) # but can get the value
>>> x.value
b'Wed Dec 31 16:00:05 1969n'
answered Mar 7 at 22:58
Mark TolonenMark Tolonen
95.4k12115177
95.4k12115177
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55050845%2fdistinguish-between-fundamental-ctypes-data-types-and-subclasses-thereof%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown