The interactive practice course for Python and C + +

Source: Internet
Author: User
Tags in python

Test environment: Win 8.1, Visual Studio, Python 3.5


First, introduce

The main purpose of the Python-C + + interaction is to speed, and the second is probably to be used as a script.

said that Python interacts with C/C + +, but in fact Python interacts with it because Python itself only supports the C API. But we can do this by tweaking the purpose of Python's collaboration with C + + engineering. Here's how Python uses the cTYPES module to interact with C in key points and problems.


second, what can be done using ctypes?

Python can invoke the C function by using the cTYPES module, which must include variable types that can define C (including struct type, pointer type).

The official definition is "ctypes are a foreign function library for Python." IT provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap this libraries in pure python. "--quote from the Python 3.5 chm document. The effect is that--ctypes is a library of external functions for Python. It provides a data type compatible with C and allows you to invoke a function in a DLL or shared library. With it, you can use pure Python to wrap these libraries (so you can import xxx directly to use these libraries).



Kothe, we need a specific example, and here we introduce a CPP file to illustrate all of the following:

The existing test.cpp documents are as follows:


#if 1
#define DLL_API __declspec (dllexport)
#else
#define DLL_API __declspec (dllimport)
#endif

#include <stdio.h>
#include <stdlib.h>

Point structural Body
struct POINT
{
float x, y;
};

static point* position = NULL;

extern "C" {

DLL_API int Add (int a, int b)
{
return a + B;
}

Dll_api float ADDF (float A, float b)
{
return a + B;
}

Dll_api void Print_point (point* p)
{
if (p)
printf ("position x%f y%f", p->x, P->y);
}
}



You can see there are three functions here, including a function with a parameter with a pointer. Learning to use Python to successfully invoke the top three functions is the goal of my article. For the Windows platform, make it a DLL file on the line (other platforms are. So). Here we write out the Python code for the test in the interpreter.



How does ctypes call C's function library?

First, you need to ctypes the function libraries that need to be called (nonsense).

Use cTYPES. Cdll, which is defined as follows (from the Python 3.5 CHM document)
cTYPES. Cdll (name, Mode=default_mode, Handle=none, Use_errno=false, Use_last_error=false)

In addition, the modes parameter is ignored on the Windows platform. For Windows platforms, you can also invoke ctypes. Windll, almost as the cdll above, the only difference is that it assumes that functions in the library follow the Windows stdcall calling convention, and other parameters are in the official document.

If you want to call the Add function in Test.dll you can write:

>>> from ctypes Import *
>>> dll = Cdll ("Test.dll") # calls Test.dll
>>> Dll.add (10, 30) # Call the Add function
40

Can see return 40, is not very simple? This is the result we expected. Let's call Addf this is the float version of Add, some people may ask why not write Dll_api float add (float A, float b) directly? Use the overload of the function just fine, why don't you do it? Note that we use the extern "C" declaration function, so the overload of the function is not supported.

Next we call ADDF and guess what will happen?

>>> DLL.ADDF (10, 30)
9108284

Oh, isn't that a little unexpected? Why is that?




Type C and Python type, parameter type, return type

Calling the ADDF function "failed" is not a problem with Python. The reason is that you didn't "tell" Python the "look" of the function (more formally, "description")--the parameter type and return type of the function. So why did we call add success? Because the Python default function has a parameter type and a return type of int. Naturally Python thought Addf returned a value of type int.

That is, the function is only known to exist when cTYPES reads the DLL, but it does not know the type of the function's parameter type and the return value. You may wonder why Python is so troublesome and tell it to share the "looks" of functions in the library. It can't be blamed, in fact, that the C # language developed by Microsoft itself needs to tell C # What this function looks like when calling a DLL. This is a bit annoying to explain, or to focus on our study of ctypes usage.

So what are the types of C for Python? Here's a list of types in Python corresponding to type C (screenshot from Python 3.5 chm document)

Then, how do you tell Python the type of the parameter and the value returned by a foreign function?

This will require assigning values to the two properties of the function ResType and argtypes. They correspond to the return type and the parameter type respectively. For ADDF its return value type is float, corresponding to Python is c_float. Here we do the assignment:

>>> dll.addf.restype = c_float # ADDF The type of return value is Flaot

If the return value of the function is void then you can assign the value to None. Also, in a version that is not too low, you can use the Python built-in type (the rightmost column in the table above) to describe the return type of the library function, but you cannot use the Python built-in type to describe the parameters of the library function.

Because the parameter of a function is not a fixed number, you need to use a list or a tuple to describe:

>>> dll.addf.argtypes = (c_float, c_float) # ADDF has two formal parameters, all float types
Or the following, but, you know, finding tuples is a little more efficient:
>>> dll.addf.argtypes = [C_float, c_float] # ADDF has two formal parameters, all float types

All that's done is done, now it's time to call ADDF:

>>> DLL.ADDF (8, 3)
11.0
>>> DLL.ADDF (8.3, 3.1)
11.399999618530273

This is the result we want.




v. More about the creation and use of ctypes types

We can also create a ctypes type (C_int, C_float, C_char ...). and assign him a value, as the following example:


>>> i = C_int (45) # defines an int type variable with a value of 45
>>> I.value # Print the value of a variable
45
>>> I.value = 56 # Change the value of this variable to 56
>>> I.value # Print new values for variables
56



Yes, you're going to assign a ctypes type by ctypes the Value property--Assigning a Python built-in type.

Other ctypes functions, such as sizeof (i) (not feeling very intimate like C), are not introduced. See article III and the official document yourself.




VI. structure and common body


This is one of the necessary components to invoke the Print_point library function.

If you want to define a C-type struct in Python, you need to define a class such as structu point to do this:

>>> class Point (Structure):
... _fields_ = [("X", C_float), ("Y", C_float)]
...
>>>

That's a good definition. There are two main points:

1. Classes must inherit from cTYPES. Structure

2. Describe the "looks" of this structure

The 1th is very simple, class XXX (Structure) on OK.

To do 2nd, you must define a property named _fields_ in the custom C-struct class and assign a value to a list as above.

You can then use this:

>>> p = Point (2,5) # defines a variable of point type, the initial value is x=2, y=5 can also write directly p = point ()
>>> p.y = 3 # Modify Value
>>> print (p.x, p.y) # Printing variables
2 3

And for the common body as long as the class inherits from cTYPES. The Union is the same as the other.




Seven, pointers

This is the last section, although the pointer, but don't be nervous, and listen to me.

How do I create a ctypes pointer? There are three functions in the ctypes with a pointer, and you will naturally be able to control them (perhaps pointer pointer will be a bit of a detour and take a closer look).
Function description
ByRef (x [, offset]) returns the address of X and x must be an instance of the cTYPES type. Equivalent to the &x of C. Offset represents the offsets.
Pointer (x) creates and returns an instance of the pointer to X, which is an instance object.
Pointer (type) returns a type, which is a pointer type of type, and type is one of the ctypes types.

ByRef is very good to understand, when passing parameters to use this, with pointer to create a pointer variable also line, but byref faster.

The difference between pointer and pointer is that pointer returns an instance pointer returns a type. You can even use pointer to do pointer work:


>>> a = C_int (66) # Create a C_int instance
>>> B = Pointer (a) # Create pointers
>>> c = Pointer (C_int) (a) # Create pointers
>>> b
<__main__. Lp_c_long Object at 0x00e12ad0>
>>> C
<__main__. Lp_c_long Object at 0x00e12b20>
>>> b.contents # Output A's value
C_long (66)
>>> c.contents # Output A's value
C_long (66)



The pointer created by pointer does not seem to be a way to modify the cTYPES type value pointed to.

All that said, next to call the Print_point function:


>>> dll.print_point.argtypes = (pointer (point),) # indicates the parameter type of the function
>>> Dll.print_point.restype = None # Indicates the return type of the function
>>>
>>> p = Point (32.4,-92.1) # Instantiate a point
>>> Dll.print_point (ByRef (P)) # calling function
Position x 32.400002 y-92.099998>>>



Of course, you have to use a slow pointer.

>>> dll.print_point (pointer (p)) # calling function
Position x 32.400002 y-92.099998>>>

The result is what we want:)

As for why the output behind the deformity "y-92.099998>>>", go over the above C code you know.




Reference Documents

More about the use of ctypes types can take you to the following books, documents, and Web pages:

1. "Python reference manual"

2. Python 3.5 Official Document "Python350.chm"

3. http://www.ibm.com/developerworks/cn/linux/l-cn-pythonandc/

Related Article

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.