python ctypes

official tutorial for ctypes lib
https://docs.python.org/3/library/ctypes.html

1 ctypes exports the cdll, and on Windows windll and oledll objects, for loading dynamic link libraries
      you should load libs by accessing them AS attrinuts of these objects, each object correspond to one call convention

2    fuctions are accessed as attributres of dll objects
      None, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls


3    Structures and unions must derive from the Structure and Union base classes which are defined in the ctypes
      By default, Structure and Union fields are aligned in the same way the C compiler does it

4    ctypes instances are objects containing a memory block plus some descriptors accessing the contents of the memory.

       Storing a Python object in the memory block does not store the object itself, instead the contents of the object is stored.

       Accessing the contents again constructs a new Python object each time

5    compared to swig, there is no complicated data structure in ctypes, such as class, no class inheritance and polymorphism

code:

// file: testlib.h
#include<stdlib.h>
#include<stdio.h>
struct Point
{
    int x;
    char *y;
};
extern "C"
{

    int  take1(int a);
    void take2(char *);
    Point * take3(Point *a);
    void take4(void (*fp)(int), int arg){fp(arg);}
}
// file: testlib.cpp

#include"testlib.h"

int take1(int a)
{
    return a+2;
}

void take2(char * pst)
{
    printf("the inpiut string is %s ", pst);
}

Point * take3(Point* a)
{
    printf("value of a of this struct is %d\n", a->x);
    printf("value of b of this struct is %s\n", a->y);
    return a;
}

to build it : g++ -std=c++11 -fpic -shared testlib.c -o libtestlib.so
python script which involks libtestlib.so

#!/usr/bin/python3

from ctypes import *
libc = CDLL('libc.so.6')

def funct1():
    print(libc.time(None))
    i = c_int(42)
    print (i)
    str = "hello, world"
    # i will be a new object, change its value will not affects the value of str
    i = c_wchar_p(str)
    print(i)
    i.value = "HELLO WOLRD"
    print(i, str)

    printf = libc.printf
    printf(b"take it, %s\n", b"James")

class Child:
    def __init__(self, age, name):
        self._as_parameter_ = age
        self.age = age
        self.name = name

def funct2():
    Tony = Child(3, b"tonny")
    printf(b"This little boy is %s, age %d \n", Tony.name, Tony.age)
    printf(b"This little boy is %d years old now\n", Tony.age)
    strchr = libc.strchr

    # specify the required arguments of fuctions exported for DLLS by setting its argtypes attribute
    # printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
    # set the return type, ctypes will do the converiton for you, which is a necessary step
    strchr.restype = c_char_p

    i = c_int()
    f = c_float()
    s = create_string_buffer(b"\000" * 32)
    # byref() pass parameters by reference, or use pointer()
    libc.sscanf(b"1 3.24 Hello", b"%d %f %s", byref(i), byref(f), s)
    print(i,f,s.value)
    libc.sscanf(b"1 3.24 Hello", b"%d %f %s", pointer(i), pointer(f), s)
    pi = pointer(i)
    print(pi.contents,f,s.value)

class POINT(Structure):
    _fields_ = [('x', c_int), ('y', c_char_p)]
    def __init__(self, x, y):
        Structure.__init__(self)
        self.x = x
        self.y = y

def funct3():
    pointa = POINT(3,4)
    print(pointa.x + pointa.y)

liba = cdll.LoadLibrary("./libtestlib.so")
def funct4():
    print(liba.take1(44))
    liba.take2(b"example 2\n")

    func3 = liba.take3
    func3.argtypes = [POINTER(POINT)]
    func3.restype = POINTER(POINT)
    charlen = 5
    databuf = (c_char * charlen)()
    for i in range(charlen):
        databuf[i] =c_char(i*2 +68)

    chrlist = cast(databuf, c_char_p)
    inputvar = POINT(charlen,chrlist)
    outputvar = func3(byref(inputvar))
    print(outputvar.contents.x)

    CB_FUNTYPE = CFUNCTYPE(None, c_int)
    def fooo(arg):
        print("the value of arg is ", arg)
    cb_func = CB_FUNTYPE(fooo);
    liba.take4(cb_func,55)

funct4()
                                                                                                                                                             

 

posted @ 2017-03-20 22:39  HEIS老妖  阅读(246)  评论(0编辑  收藏  举报