Dies ist die Support Website des Buches:
Das Python Praxisbuch
Der große Profi-Leitfaden für Programmierer
Farid Hajji
Addison Wesley / Pearson Education
ISBN 978-3-8273-2543-3 (Sep 2008), 1298 Seiten.
11. Python und C/C++¶
ctypes¶
Die ctypes-Datentypwrapper¶
Komplexe Datentypen¶
Die Funktionen assctime
und erand48
:
char * asctime(const struct tm *); /* <time.h> */
double erand48(unsigned short[3]); /* <stdlib.h> */
ctypes-Pointer¶
ctypes-Strukturen und -Unions¶
Die C-Structur tm
:
struct tm {
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
int tm_hour; /* hours since midnight [0-23] */
int tm_mday; /* day of the month [1-31] */
int tm_mon; /* months since January [0-11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
long tm_gmtoff; /* offset from UTC in seconds */
char *tm_zone; /* timezone abbreviation */
};
#!/usr/bin/env python
# time_tm.py -- ctypes wrapper for <time.h> struct tm;
from ctypes import Structure, c_int, c_long, c_char_p
class tm(Structure):
_fields_ = [ ("tm_sec", c_int), # seconds after the minute [0-60]
("tm_min", c_int), # minutes after the hour [0-59]
("tm_hour", c_int), # hours since midnight [0-23]
("tm_mday", c_int), # day of the month [1-31]
("tm_mon", c_int), # months since January [0-11]
("tm_year", c_int), # years since 1900
("tm_wday", c_int), # days since Sunday [0-6]
("tm_yday", c_int), # days since January 1 [0-365]
("tm_isdst", c_int), # Daylight Savings Time flag
("tm_gmtoff", c_long), # offset from UTC in seconds
("tm_zone", c_char_p), # timezone abbreviation
]
ctypes-Arrays¶
Die Klasse XZY
:
class XZY(Structure):
_fields_ = [ ("point", c_ushort * 3),
("rgb", c_ubyte * 3)
]
C-Funktionen aufrufen¶
Funktionen aus Bibliotheken laden¶
URLs:
Screenshots:
Aus der Unix libc
laden:
from ctypes import *
libc = cdll.LoadLibrary("libc.so")
libc.sleep(5)
Aus Windows DLLs laden:
from ctypes import *
kernel32 = windll.kernel32
user32 = windll.user32
msvcrt = cdll.msvcrt
MessageBoxW = user32.MessageBoxW
MessageBoxW(0, u'A Unicode Message: ÄÖÜäöüß', u'A Unicode Greeter', 0)
Hier hatte MessageBox
(ANSI und Wide) die Signatur:
int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
Und printf
ruft man so aus:
>>> from ctypes import *
>>> printf = cdll.msvcrt.printf
>>> result = printf("Hello, %s. You are %d years old.\n",
... "John", 39)
Hello, John. You are 39 years old.
>>> result
35
Funktionen, die Strings auslesen: getenv, setenv¶
char *getenv(const char *name);
int setenv(const char *name, const char *value, int overwrite);
Die nötigen Vorbereitungen:
from ctypes import *
libc = cdll.LoadLibrary("libc.so")
getenv = libc.getenv
setenv = libc.setenv
getenv.argtypes = [c_char_p]
getenv.restype = c_char_p
setenv.argtypes = [c_char_p, c_char_p, c_int]
setenv.restype = c_int
URLs:
Funktionen, die in einen Puffer schreiben¶
int gethostname(char *name, size_t namelen); /* <unistd.h> */
Die nötigen Vorbereitungen:
from ctypes import *
libc = cdll.LoadLibrary("libc.so")
gethostname = libc.gethostname
gethostname.argtypes = [c_char * 255, c_uint]
gethostname.restype = c_int
buf = create_string_buffer(255)
URLS:
DWORD WINAPI GetEnvironmentVariable(
__in_opt LPCTSTR lpName,
__out_opt LPTSTR lpBuffer,
__in DWORD nSize
);
Screenshots:
Funktionen mit struct und pointer: gmtime, asctime¶
time_t time(time_t *tloc); /* <time.h> */
struct tm * gmtime(const time_t *clock); /* <time.h> */
char * asctime(const struct tm *tm); /* <time.h> */
URLs:
SWIG¶
URLs:
SWIG installieren¶
URLs:
- http://prdownloads.sourceforge.net/swig/ (Neueste Versionen von swig, macswig und swigwin)
SWIG unter Unix installieren¶
SWIG aufrufen¶
%module sleeper
unsigned int sleep(unsigned int seconds);
#!/usr/bin/env python
from distutils.core import setup, Extension
sleeper_module = Extension('_sleeper',
sources = ['sleeper_wrap.c', ],
)
setup(name = 'sleeper',
version = '0.1',
author = 'Farid Hajji',
description = '''Wrapping sleep(3)''',
ext_modules = [sleeper_module],
py_modules = ["sleeper"],
)
C-Code mitkompilieren¶
/* deepthought.h -- a complex function */
#ifndef _DEEPTHOUGHT_H_
#define _DEEPTHOUGHT_H_
#define THE_ANSWER 42
extern int answer(void);
#endif /* _DEEPTHOUGHT_H_ */
/* deepthought.c -- a complex function */
#include "deepthought.h"
int answer(void) {
return THE_ANSWER;
}
%module deepthought
%{
#include "deepthought.h"
%}
int answer(void);
#!/usr/bin/env python
from distutils.core import setup, Extension
deepthought_module = Extension('_deepthought',
sources = ['deepthought.c',
'deepthought_wrap.c', ],
)
setup(name = 'deepthought',
version = '0.1',
author = 'Farid Hajji',
description = '''A complex function''',
ext_modules = [deepthought_module],
py_modules = ["deepthought"],
)
Screenshots:
Konstanten und Variablen¶
Konstanten¶
/* math_constants.h -- some math.h constants */
#ifndef _MATH_CONSTANTS_H_
#define _MATH_CONSTANTS_H_
#define MM_E 2.7182818284590452354 /* e */
#define MM_LOG2E 1.4426950408889634074 /* log 2e */
#define MM_LOG10E 0.43429448190325182765 /* log 10e */
#define MM_LN2 0.69314718055994530942 /* log e2 */
#define MM_LN10 2.30258509299404568402 /* log e10 */
#define MMAXFLOAT ((float)3.40282346638528860e+38)
enum Integers { ZERO, ONE, TWO, THREE, FOUR, FIVE };
const double MM_PI = 3.14159265358979323846; /* pi */
const double MM_PI_2 = 1.57079632679489661923; /* pi/2 */
const double MM_PI_4 = 0.78539816339744830962; /* pi/4 */
#endif /* _MATH_CONSTANTS_H_ */
%module math_constants
%{
#include "math_constants.h"
%}
#define MM_E 2.7182818284590452354 /* e */
#define MM_LOG2E 1.4426950408889634074 /* log 2e */
#define MM_LOG10E 0.43429448190325182765 /* log 10e */
#define MM_LN2 0.69314718055994530942 /* log e2 */
#define MM_LN10 2.30258509299404568402 /* log e10 */
#define MMAXFLOAT ((float)3.40282346638528860e+38)
enum Integers { ZERO, ONE, TWO, THREE, FOUR, FIVE };
%constant double MM_PI;
%constant double MM_PI_2;
%constant double MM_PI_4;
#!/usr/bin/env python
from distutils.core import setup, Extension
math_constants_module = Extension('_math_constants',
sources = ['math_constants_wrap.c',],
)
setup(name = 'math_constants',
version = '0.1',
author = 'Farid Hajji',
description = '''Wrapping constants in math_constants.h''',
ext_modules = [math_constants_module],
py_modules = ["math_constants"],
)
Globale Variablen: cvar¶
/* globvar.h -- global variables */
#ifndef _GLOBVAR_H_
#define _GLOBVAR_H_
extern int get_value(void);
extern void set_value(int value);
extern int global_var;
#endif /* _GLOBVAR_H_ */
/* globvar.c -- global variables */
#include "globvar.h"
int
get_value(void) {
return global_var;
}
void
set_value(int value) {
global_var = value;
}
/* A global variable shared by set_value and get_value */
int global_var = 0;
%module globvar
%{
#include "globvar.h"
%}
extern int get_value(void);
extern void set_value(int value);
extern int global_var;
#!/usr/bin/env python
from distutils.core import setup, Extension
globvar_module = Extension('_globvar',
sources = ['globvar_wrap.c',
'globvar.c'],
)
setup(name = 'globvar',
version = '0.1',
author = 'Farid Hajji',
description = '''Wrapping a global variable''',
ext_modules = [globvar_module],
py_modules = ["globvar"],
)
%module globvar_ro
%{
#include "globvar.h"
%}
extern int get_value(void);
extern void set_value(int value);
%immutable;
extern int global_var;
%mutable;
#!/usr/bin/env python
from distutils.core import setup, Extension
globvar_ro_module = Extension('_globvar_ro',
sources = ['globvar_ro_wrap.c',
'globvar.c'],
)
setup(name = 'globvar_ro',
version = '0.1',
author = 'Farid Hajji',
description = '''Wrapping a global variable''',
ext_modules = [globvar_ro_module],
py_modules = ["globvar_ro"],
)
%module globvar_noglobals
%{
#include "globvar.h"
%}
extern int get_value(void);
extern void set_value(int value);
#!/usr/bin/env python
from distutils.core import setup, Extension
globvar_noglobals_module = Extension('_globvar_noglobals',
sources = ['globvar_noglobals_wrap.c',
'globvar.c'],
)
setup(name = 'globvar_noglobals',
version = '0.1',
author = 'Farid Hajji',
description = '''Wrapping a global variable''',
ext_modules = [globvar_noglobals_module],
py_modules = ["globvar_noglobals"],
)
Stringmanipulationen¶
C-Funktionen, die Strings lesen¶
char *getenv(const char *name);
int setenv(const char *name, const char *value, int overwrite);
URLs:
%module environ
%{
#include <stdlib.h>
%}
char *getenv(const char *name);
int setenv(const char *name, const char *value, int overwrite);
C-Funktionen, die Strings verändern¶
int gethostname(char *name, size_t namelen); /* <unistd.h> */
URLS:
%module hostname
%include "cstring.i"
%{
#include <unistd.h>
%}
%cstring_output_maxsize(char *name, size_t namelen);
int gethostname(char *name, size_t namelen);
Strukturen¶
time_t time(time_t *tloc); /* <time.h> */
struct tm * gmtime(const time_t *clock); /* <time.h> */
char * asctime(const struct tm *tm); /* <time.h> */
URLs:
%module tm
%include typemaps.i
%{
#include <time.h>
%}
typedef int time_t;
char *asctime(const struct tm *INPUT);
struct tm *gmtime(const time_t *INPUT);
time_t time(time_t *);
%module tm_verbose
%include typemaps.i
%{
#include <time.h>
%}
struct tm {
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
int tm_hour; /* hours since midnight [0-23] */
int tm_mday; /* day of the month [1-31] */
int tm_mon; /* months since January [0-11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
long tm_gmtoff; /* offset from UTC in seconds */
char *tm_zone; /* timezone abbreviation */
};
typedef int time_t;
char *asctime(const struct tm *INPUT);
struct tm *gmtime(const time_t *INPUT);
time_t time(time_t *);
C++ Klassen¶
// person.h -- a C++ class
#ifndef _PERSON_H_
#define _PERSON_H_
#include <string>
class Person {
public:
Person(const char *name);
Person(const Person &anotherOne);
virtual ~Person();
const std::string &get_name(void) const;
void set_name(const char *newname);
private:
std::string name_;
};
#endif /* _PERSON_H_ */
// person.cxx -- a C++ class
#include <iostream>
#include "person.h"
Person::Person(const char *name)
{
name_ = std::string(name);
}
Person::Person(const Person &anotherOne)
{
name_ = std::string(anotherOne.get_name());
}
Person::~Person()
{
std::cout << "Person::~Person() called" << std::endl;
}
const std::string & Person::get_name(void) const
{
return name_;
}
void Person::set_name(const char *newname)
{
name_ = std::string(newname);
}
// person_test.cxx -- testing the Person class
#include <iostream>
#include "person.h"
int main(int argc, char *argv[])
{
Person p("John Doe");
std::cout << "Name of p: " << p.get_name() << std::endl;
p.set_name("Jane Doe");
std::cout << "Name of p: " << p.get_name() << std::endl;
Person p2(p);
std::cout << "Name of p2: " << p2.get_name() << std::endl;
return 0;
}
%module person
%include "std_string.i"
%{
#include "person.h"
%}
class Person {
public:
Person(const char *name);
Person(const Person &anotherOne);
virtual ~Person();
const std::string &get_name(void) const;
void set_name(const char *newname);
private:
std::string name_;
};
#!/usr/bin/env python
from distutils.core import setup, Extension
person_module = Extension('_person',
sources = ['person_wrap.cxx',
'person.cxx'],
)
setup(name = 'person',
version = '0.1',
author = 'Farid Hajji',
description = '''Wrapping C++ class Person''',
ext_modules = [person_module],
py_modules = ["person"],
)
Unbekannte Datentypen sind Pointer¶
#include <unistd.h>
gid_t getegid(void);
uid_t geteuid(void);
URLs:
%module uid
gid_t getegid(void);
uid_t geteuid(void);
%module uid
typedef int gid_t;
typedef int uid_t;
gid_t getegid(void);
uid_t geteuid(void);
%module fileio
FILE *fopen(char *, char *);
int fclose(FILE *);
unsigned fread(void *ptr, unsigned size, unsigned nobj, FILE *);
unsigned fwrite(void *ptr, unsigned size, unsigned nobj, FILE *);
void *malloc(int nbytes);
void free(void *);
#!/usr/bin/env python
# filecopy.py -- copy binary files with <stdio.h> functions.
#
# Source: SWIG Documentation.
from fileio import *
BLOCKSIZE = 8192
def filecopy(source, target):
'''Copy file SOURCE to TARGET using fread/fwrite.
The source file MUST contain a multiple of BLOCKSIZE bytes.
If not, the last block will NOT be copied over!'''
f1 = fopen(source, "r")
f2 = fopen(target, "w")
buf = malloc(BLOCKSIZE)
nrecs = fread(buf, BLOCKSIZE, 1, f1)
while nrecs > 0:
fwrite(buf, BLOCKSIZE, 1, f2)
nrecs = fread(buf, BLOCKSIZE, 1, f1)
free(buf)
fclose(f2)
fclose(f1)
URLs zum Verständnis von filecopy.py
:
Wie geht’s von hier aus weiter?¶
Boost.Python¶
URLs: