Ctypes calls dll and ctypesdll

Source: Internet
Author: User

Ctypes calls dll and ctypesdll
1. Load Windows API and C Runtime Library

First look at the example

From ctypes import * u32 = windll. loadLibrary ('user32. dll ') # Load user32.dllu32. messageBoxW (0, u 'content', u 'title', 0) crt = cdll. loadLibrary ('msvcrt. dll ') # load the C Runtime crt. printf ('Hello world! \ N ')

Call C library to use cdll, while call Windows API to use windll.

The difference between cdll and windll is that the calling rules for Windows API and C library functions are different. The former follows _ stdcall and the latter follows _ cdecl.

_ Cdecl is short for C Declaration, which indicates the default function call specification of the C compiler. In this way, the caller is responsible for clearing the parameter stack. For example, in VC, if no modifier is added before the function, the default value is _ cdecl.

_ Stdcall is short for Standard Call. In this way, the called function is responsible for clearing the parameter stack. In VC, if _ stdcall is modified before the function, this type is compiled.

All Windows APIs use _ stdcall. Because Windows APIs are called by various languages in various compilers, if the _ cdecl method is used, the stack structure used in various compilers may be different, therefore, we cannot guarantee that each of the compilers can properly clean up the parameter stacks generated by Windows APIs. In the _ stdcall mode, the caller can clear the parameter stack by himself to avoid the above troubles.

In Windows, the LoadLibrary () parameter may not include the extension. There is also a simpler method, for example, the following three are equivalent:

From ctypes import * windll. loadLibrary ('user32. dll '). messageBoxW (0, u'content', u'title', 0) windll. loadLibrary ('user32 '). messageBoxW (0, u'content', u'title', 0) windll. user32.MessageBoxW (0, u'content', u'title', 0)
The same is true for the following three items:
from ctypes import *cdll.LoadLibrary('msvcrt.dll').printf('hello world !\n')cdll.LoadLibrary('msvcrt').printf('hello world !\n')cdll.msvcrt.printf('hello world !\n')

2. implicit type conversion

Int, str, unicode, these three types can be passed directly as parameters, do not specify the corresponding C type

from ctypes import *cdll.msvcrt.printf('%d, %s\n', 100, 'abc')

3. Explicit type conversion

Int, str, and unicode types must be explicitly converted when used as parameters, indicating the corresponding C type

from ctypes import *cdll.msvcrt.printf('%.2f\n', c_double(3.14))

4. pointer and reference

Byref () can reference the memory address, which is equivalent &

from ctypes import *i = c_int(0)cdll.msvcrt.sscanf('100', '%d', byref(i))print i.value
Pointer () can also achieve the same effect
from ctypes import *i = c_int(0)cdll.msvcrt.sscanf('100', '%d', pointer(i))print i.value
The difference between the two is that pointer () constructs a pointer object, and byref () is just a function, so the overhead of byref () is small.

If it is only used to pass parameters, it is enough to use byref.

5. String pointer

Use create_string_buffer () and create_unicode_buffer ()

From ctypes import * s = create_string_buffer ('abc') # Initial value abccdll. msvcrt. sscanf ('def ',' % s', s) print s. value # def

6. Callback Function

To test the callback function, first write a test. dll. below is the C code

 #include <stdio.h> typedef void __stdcall (*MyCallback)(int);__declspec(dllexport) void __stdcall TestMyCallback( int i, MyCallback mycallback){    printf("TestMyCallback:%d\n", i);    mycallback(i*10);}
The above function accepts two parameters: the first is the integer variable I, and the second is a callback function.

Print the variable I first, and then pass I * 10 to the callback function.

The (_ declspec (dllexport) keyword is used to export a function from a dll. For details, see here)

The following Python code implements the callback function and passes it to test. TestMyCallbackPython

From ctypes import * def mycallback (I): print 'mycallback: ', ic_mycallback = WINFUNCTYPE (None, # Return Value Type None represents void c_int # first parameter type int) (mycallback) # The Python function windll to be packaged is enclosed in brackets. test. testmycallback( 100, c_mycallback)
The usage of WINFUNCTYPE includes two steps:

  • First, declare a C function prototype.
    C_function_type = WINFUNCTYPE (return value type, first parameter type, second parameter type ...)
  • Then use this prototype to encapsulate the Python function.
    C_function = c_function_type (Python function)

WINFUNCTYPE complies with _ stdcall call specifications. The corresponding version of _ cdecl is CFUNCTYPE.


Python ctypes Call dll parameter conversion problems

From ctypes import *

Code = c_char_p ('')

Market = c_int (10)

Dll = windll. LoadLibrary ("./hello. dll ")

Print dll. GetStockMin (code, market)

Try it
 
An error is returned when python calls a function in the dll.

It seems that you have not loaded the DLL in the code.
In addition, it may be inappropriate for you to directly rewrite python memory in c. It is usually constructed in C and then returned to python.

From the perspective of your program, after calling Thin, your Variable p seems to have become a null pointer.

Ctypes Call DLL is usually prepared by others, and there is no way to call it by yourself. There are a lot of troubles here.

If you write your own code, we recommend that you use the cython module. It is easy to implement interfaces. You don't have to worry about the encapsulation of these variable types and interfaces.

In addition, the dll seems to have something to do with the compiler. It may be easier to use VC. Using BC or GCC is troublesome.

There is also a version issue, 64-bit and 32-bit cannot be used.

In principle, it is not impossible for you to use this method. It is possible that you have not made any mistakes. For example, compile parameters. You can try to use return type to bring data back. Instead of writing memory with pointers.

Because p is a constant, it is very likely that it will not be rewritten in the calling mechanism.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.