I am trying to use SSL library in Python and I need to write a clone code of a C++ code.
In C SSL function is called like this:
EVP_MD_CTX mdctx;
EVP_MD_CTX_init(&mdctx)
In Python I reached SSL library:
import ctypes
import ctypes.util
import platform
from os import linesep
libraries = {}
libraries["c"] = ctypes.CDLL(ctypes.util.find_library("c"))
if platform.system() != "Windows":
libraries["ssl"] = ctypes.CDLL(ctypes.util.find_library("ssl"))
else:
libraries["ssl"] = ctypes.CDLL(ctypes.util.find_library("libeay32"))
EVP_MD_CTX_init = libraries['ssl'].EVP_MD_CTX_init
EVP_MD_CTX_init.restype = ctypes.c_void_p
EVP_MD_CTX_init.argtypes = [ctypes.c_void_p]
Which is taken from here
How may I pass EVP_MD_CTX_init function by reference as it is made in C?
Since I have no access to EVP_MD_CTX_init() method.I have to call this method with 'pass by reference'
I tried EVP_MD_CTX_init(ctypes.byref(mdctx)) but syntax error is occured.Is there any way to do this?
You should consult the ctypes documentation.
The way to go is to use byref() or pointer() (slower and more complex) functions exported by ctypes module, as seen in the example.
>>> print ctypes.byref.__doc__
byref(C instance[, offset=0]) -> byref-object
Return a pointer lookalike to a C instance, only usable
as function argument
This is explained in the ctypes docs, in Passing pointers (or: passing by reference):
Sometimes a C api function expects a pointer to a data type as parameter, probably to write into the corresponding location, or if the data is too large to be passed by value. This is also known as passing parameters by reference.
ctypes exports the byref() function which is used to pass parameters by reference. The same effect can be achieved with the pointer() function, although pointer() does a lot more work since it constructs a real pointer object, so it is faster to use byref() if you don’t need the pointer object in Python itself:
>>> i = c_int()
>>> f = c_float()
>>> s = create_string_buffer(b'\000' * 32)
>>> print(i.value, f.value, repr(s.value))
0 0.0 b''
>>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",
... byref(i), byref(f), s)
3
>>> print(i.value, f.value, repr(s.value))
1 3.1400001049 b'Hello'
However, now that you're provided the code, you're not trying to pass it to a C function that expects a pointer, you're trying to pass it to a Python function.
If you wanted to do that, as the docs explain, you need to use pointer rather than byref. And of course the Python function needs to expect a POINTER(c_int) rather than a c_int.
But in that, you're not even really doing that. You've written this code:
a=ctypes.c_int(35)
def foo(n):
n=ctypes.c_int(19)
You're not doing anything to the value that was passed in; you're just rebinding the local name n to a different, newly-constructed value.
All you need to do here is change the value:
def foo(n):
n.value = 19
Then there's no need for a byref or a pointer here.
Related
I am trying to access GPIO of my IDS camera via python using pyueye. The original function is defined as: INT is_IO(HIDS hCam, UINT nCommand, void* pParam, UINT cbSizeOfParam). This is an example of usage:
Example 2
INT nRet = IS_SUCCESS;
IO_GPIO_CONFIGURATION gpioConfiguration;
// Set configuration of GPIO1 (OUTPUT LOW)
gpioConfiguration.u32Gpio = IO_GPIO_1;
gpioConfiguration.u32Configuration = IS_GPIO_OUTPUT;
gpioConfiguration.u32State = 0;
nRet = is_IO(hCam, IS_IO_CMD_GPIOS_SET_CONFIGURATION, (void*)&gpioConfiguration,
sizeof(gpioConfiguration));
I'm trying to do it in python as follows:
from pyueye import ueye
from ctypes import pointer
gpioConfiguration = ueye.IO_GPIO_CONFIGURATION
gpioConfiguration.u32Gpio = ueye.IO_GPIO_1
gpioConfiguration.u32Configuration = ueye.IS_GPIO_OUTPUT
gpioConfiguration.u32State = 1
pt = pointer(gpioConfiguration)
stat = ueye.is_IO(hCam, ueye.IS_IO_CMD_GPIOS_SET_CONFIGURATION,byref(gpioConfiguration),ueye.sizeof(gpioConfiguration))
But I get the error: TypeError: type must have storage info.
Any ideas on what I need to change?
The error is actually being thrown by your call to ctypes.pointer rather than pyueye. Specifically, gpioConfiguration is a _ctypes.PyCStructType rather than an instance. (This is what was meant by 'must have storage', i.e. you actually have to store something looking like that struct before you can get a pointer to it. This is likely a bit odd coming from c++, but ctypes thinks of structs as being like Classes you have to instantise. docs.
So if you really needed a pointer you would have to do:
myConfig = gpioConfiguration()
pt = pointer(myConfig)
# you probably want to set properties on the *instance*:
myConfig.u32Gpio = ueue.IO_GPIO_1
myConfig.u32State = 1
# and then use this instance later when passing `byref`
If you just need to pass these params by reference, see the section on byref (though this too needs an instance).
I don't have a camera to test with sadly (they look very good fun), so this is far as I can go. But hopefully you can get the semantics of ueye behaving for you.
Incidentally, you don't need semicolons in python (unlike in JS you really don't and nobody thinks you should put them in)
Python Version
Python 3.5.2
Issue
I notice this issue when I tried to call the C DLL using ctypes, the C function is something like:
MEASURE_API int InitTester(char *ipAddress)
So I need to pass an IP address string (for example, 192.168.100.100) from Python to ctypes, according to ctypes doc of Python 3.5, I tried both c_wchar_p and c_char_p, but none of them working, I got error code retrun from c dll side. I had some other function call to this dll passing c_int, c_void_p, c_bool and other data types which are all ok. Traced back and found that the c_wchar_p and c_char_p return results behaves different from what it should be based on ctypes doc. From the ctypes doc of Python 3.5:
>>> c_wchar_p("Hello, World")
c_wchar_p('Hello, World')
It return the ctypes string.
But my results of execute the same cmd in Python console:
>>> from ctypes import *
>>> c_wchar_p("Hello, World")
c_wchar_p(1374004842736)
>>> c_wchar_p("Hello, World")
c_wchar_p(1374004841680)
>>> c_wchar_p("Hello, World")
c_wchar_p(1374004842736)
So seems like the orignial string part becomes memory address maybe. Digged in more, and found out if it is Python 2.x(default encoding is ASCII), then the return shows the string like the Python 3.5 ctypes doc shows. But in Python 3.x(default encoding is UTF-8), it always return numbers, behave differnt from the doc. Checked on multiple PCs. And understood the part that, we can use .value to return the original string. But it could not pass to the C function which has to be a ctype.
Question
Can anyone provide a explaination about this about behavior ctypes?
and how to resolve this, so that I could get the same behave like ctype doc in Python3.5 and then make the call c dll work?
Thanks a lot in advance~
I am more than certain now that you should be using create_string_buffer instead of c_char_p for passing the string to your C function; the non-const signature indicates a mutation and that requires a character buffer as stated in the docs:
You should be careful, however, not to pass them to functions expecting pointers to mutable memory. If you need mutable memory blocks, ctypes has a create_string_buffer() function which creates these in various ways. The current memory block contents can be accessed (or changed) with the raw property; if you want to access it as NUL terminated string, use the value property.
(emphasis mine)
So in essence, create_string_buffer(b'192.168.100.100').
Aside from that, it just seems that the documentation might indeed be off on this. The implementation of __repr__ for c_char_p and c_wchar_p returns their name and, after a pointer to their memory buffer has been created, the .value that c_void_p pointer.
I'm currently getting into the ctypes module and I'm trying to call the user32 function GetWindowText with a HWND handle I already received by using FindWindow. This time though i wanted to process a step further and use a function prototype instead of calling the function with ctypes.windll.user32.GetWindowText. Although I´m having problems declaring the lpString arguement as output parameter.
My first attempt looked this way:
GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",LPCSTR,2),
("nMaxCount",c_int,1)
)
(cfunc is a little wrapper that I found here)
This prototype yields the following exception as soon as it is called:
chars,name = user32.GetWindowText(handle,255)
TypeError: c_char_p 'out' parameter must be passed as default value
I thought that any output variables must be a POINTER(...) type, so I changed my definition to:
GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char),2),
("nMaxCount",c_int,1)
)
But this yields an exception too:
chars,name = user32.GetWindowText(handle,255)
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: wrong type
I hope somebody knows how to call the GetWindowText function correctly using ctypes prototyping.
Edit:
Through further research I could get it to work, at least somehow. The first issue I fixed was the usage of cfunc() which had wrong calling specifiers. I defined a exact copy of that function and named it winfunc() and replaced return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags)) with return WINFUNCTYPE(result, *atypes)((name, dll), tuple(aflags)).
Then I inspected prototyping further. As it seems if you pass somewhat like ("someParameter",POINTER(aType),2) to WINFUNCTYPE it will create a aType object on call and passes a pointer to that object to the function. In the returned tuple you can then access the aType object. This brings up another problem. A cstring is a array of chars; so one needs to tell ctypes to create a c_char array. This means that something like:
GetWindowText = winfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char*255),2),
("nMaxCount",c_int,1)
)
works just fine. But unfortunately, ctypes will now pass a pointer to a cstring which is ALWAYS 255 chars long ignoring the size specified by nMaxCount.
In my opinion, I think theres no way one could get that function to work with a dynamically sized cstring defined as output parameter. The only possibility seems to be simply going without the output parameter feature and defining a LPCSTR as input parameter. The callee then needs to create a buffer by his own with ctypes.create_string_buffer() and pass it to the function (just as in C).
You have to create a string buffer for out parameters. You can wrap the function to make it somewhat transparent:
# python3
from ctypes import *
_GetWindowText = WinDLL('user32').GetWindowTextW
_GetWindowText.argtypes = [c_void_p,c_wchar_p,c_int]
_GetWindowText.restype = c_int
def GetWindowText(h):
b = create_unicode_buffer(255)
_GetWindowText(h,b,255)
return b.value
FindWindow = WinDLL('user32').FindWindowW
FindWindow.argtypes = [c_wchar_p,c_wchar_p]
FindWindow.restype = c_void_p
h = FindWindow(None,'Untitled - Notepad')
print(GetWindowText(h))
Or in this case you can just use pywin32:
import win32gui
h = win32gui.FindWindow(None,'Untitled - Notepad')
print(win32gui.GetWindowText(h))
Yep. You have to create the buffer for every call. If you let the function definition do it, how will you able to access the buffer later?
You also seem to have to tell it to expect a pointer c_char with POINTER(c_char), and not simply c_char_p or LPSTR. Not sure why that happens though.
Anyway, this should work:
from ctypes import *
from ctypes.wintypes import *
# defs
FindWindowF = WINFUNCTYPE(HWND, LPSTR, LPSTR)
FindWindow = FindWindowF(windll.user32.FindWindowA)
GetWindowTextF = WINFUNCTYPE(c_int, HWND, POINTER(c_char), c_int)
GetWindowText = GetWindowTextF(windll.user32.GetWindowTextA)
# code
text = create_string_buffer(255)
hwnd = FindWindow(None, 'Untitled - Notepad')
GetWindowText(hwnd, text, sizeof(text))
print text.value
I am trying to write a wrapper to a native library in Linux. Problem is this:
definition in c:
int mymethod(mystruct* ptr)
in python:
_lib.mymethod.argtypes = (ctypes.POINTER(mystruct),)
_lib.mymethod.restype = ctypes.c_int
s = mystruct()
_lib.mymethod(ctypes.byref(s))
# raises: expected LP_mystruct instance instead of pointer to mystruct
_lib.mymethod(ctypes.pointer(s))
# raises expected LP_mystruct instance instead of LP_mystruct
errors. How to pass a structure as a pointer to a native method ?
Thanks.
Mete
The problem is that the higher level "POINTER" from ctypes is, in Python, a different object than "a generic pointer" (ctypes.CArgObject by ctypes.byref)which is returned or a single number representing a memory address (which is what is returned by ctype's adrresof) - you can either annotate your function to receive a `ctypes.c_voidp and call it with _lib.mymethod(ctypes.addressof(a)) instead -
Or if you want to work on the stronged-typed side to avoid errors that would crash Python (a type error raises a Python exception instead - a wrong parameter passed to a C unction would cause a segmentation fault on the Python interpreter itself), you have to create a variable to hold the new "type" which is a POINTER to your structure - and then create an instance of this type with the address of your structure:
mystruct_pointer = ctypes.POINTER(mystruct)
_lib.mymethod.argtypes = (mystruct_pointer,)
_lib.mymethod.restype = ctypes.c_int
s = mystruct()
_lib.mymethod(mystruct_pointer.from_address(ctypes.addressof(s)))
(I know that this is an old question, but I think the accepted answer is an unnecessary workaround, so I want to leave this here for posterity.)
Actually ctypes should explicitly support using byref() to pass a pointer like that:
ctypes exports the byref() function which is used to pass parameters by reference. The same effect can be achieved with the pointer() function, although pointer() does a lot more work since it constructs a real pointer object, so it is faster to use byref() if you don’t need the pointer object in Python itself.
The likely cause of this is that you have defined your struct in more than one place (e.g. in different modules) - if the argtypes assignment sees one definition and the function call sees the other, this confusing error arises. In other words, ctypes tries to match two mystruct types that are (probably) identical in contents, and have the exact same name, but they are not the same type. As long as the base struct type is a single type object, it doesn't matter if you construct a pointer to it using pointer(), byref() or POINTER()() - ctypes will detect that the underlying (pointed-to) type is the same.
To verify if this is the case, try assert(_lib.mymethod.argtypes[0]._type_ == type(s)) right before calling the external function.
I am interfacing with a library that returns opaque pointers. Is it acceptable to subclass c_void_p to represent this in ctypes and provide for type checking for this particular flavor of c_void_p?
An easy way to do this type checking might be to create some arbitrary ctypes.Structure
class _Opaque(ctypes.Structure):
pass
Declare the return type of the relevant functions to be a pointer to this structure
lib.f.restype = ctypes.POINTER(_Opaque)
and either the argument type of a function which accepts this kind of pointer again:
lib.g.argtypes = [ctypes.POINTER(_Opaque)]
Now, ctypes ensures that the parameter to g is a pointer that was returned by f before. (Note that I used a leading _ to mark _Opaque for uses in this module only.)