Compare commits

..

1 Commits

Author SHA1 Message Date
Colin Xu
98980c4414 Enable pykd for python 3.10.
Signed-off-by: Colin Xu <colin.xu@gmail.com>
2023-02-21 20:50:54 -08:00
74 changed files with 6972 additions and 3457 deletions

View File

@ -1,18 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
[Description]
Describe the reproduce step and symptom with details. If applicable, add attachment, code snippets or screenshots to help explain your problem.
[Configuration]
- OS: (i.e Windows 11 24H2, 64bit)
- WinDbg: (i.e. 10.0.26100.2454, AMD64)
- Python: (i.e. 3.10.11, 64bit)
- pykd: (i.e. 0.3.4.15, check with python -m pip list)
- pykd.dll: (i.e. 2.0.0.25, check with windbg command ".chain")

6
.gitignore vendored
View File

@ -1,6 +1,2 @@
*.pyc
.vs .vs
Out/
Obj/
cmake/
packages/
*.vcxproj.user

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "kdlibcpp"] [submodule "kdlibcpp"]
path = kdlibcpp path = kdlibcpp
url = https://github.com/ivellioscolin/kdlibcpp.git url = https://github.com/ivellioscolin/kdlibcpp.git
[submodule "pykd_ext"]
path = pykd_ext
url = https://github.com/ivellioscolin/pykd-ext.git

Binary file not shown.

View File

@ -1,19 +0,0 @@
# Changelog
All notable changes to the pykd maintenance fork will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
## [Unreleased]
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
## [0.3.4.15_2] - 2023-02-27
### Added
- Support Python 3.11
## [0.3.4.15_1] - 2023-02-22
### Added
- Support Python 3.10.

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2025 pykd Copyright (c) 2017 pykd
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,17 +1,66 @@
# pykd Maintenance # Pykd - not only python extension for WinDBG
The repo is trying to continue the maintenance as the original project page is no longer accessible. ## Purpose
This project can help to automate debugging and crash dump analysis using Python. It allows one to take the best from both worlds: the expressiveness and convenience of Python with the power of WinDbg!
## [Links] ## Why do I need this?
- [Project Page](https://githomelab.ru/pykd/pykd) If you want to automate the debugger but dislike the WinDbg built-in script machine syntax it's time to try again using the handy and powerful Python language. Even if you don't want to create your own script, maybe some existing scripts will be of interest to you?
- [Web Archive](https://web.archive.org/web/20230321180029/https://githomelab.ru/pykd/pykd)
## [Maintenance Release] ## Getting started
- 0.3.4.15_2 - 2023-02-27 * You should have installed python. Supported python: 2.7, 3.5 - 3.9
- 0.3.4.15_1 - 2023-02-22 * Install pykd with command: 'pip install pykd'
* Use windbg extension (bootstrapper) to run pykd with windbg
## [Change log] ## Windbg extension (bootstarpper)
Check [CHANGELOG](CHANGELOG.md) for the maintenance updates. Use it to run pykd within windbg.
[Home Page](https://githomelab.ru/pykd/pykd-ext)
[Download](https://githomelab.ru/pykd/pykd-ext/wikis/Downloads)
## [Read Me] ## Releases
Check the original [README](README_OLD.md) for more information about pykd. Just run 'pip install pykd' to install or 'pip install pykd --upgrade' to upgrade to the last version
[PyPi](https://pypi.org/project/pykd)
[All Releases](/../wikis/All Releases)
## Documentation
[Wiki Home](/../wikis/Home)
[User Manual](/../wikis/User Manual rus)
[API Reference](/../wikis/API Reference)
## Useful tools for pykd and WinDBG
[windbg-pack](https://githomelab.ru/pykd/windbg-pack)
Set of python scripts for WinDBG
[pykdwin](https://githomelab.ru/pykd/pykdwin)
A library with auxiliary modules for writing small pykd scripts and daily use.
[windbg-kernel](https://githomelab.ru/pykd/windbg-kernel)
Set of pykd script for kernel debugging
## How to build ?
* install VS 2017
https://visualstudio.microsoft.com/downloads/
* install cmake
https://cmake.org/
* install git
https://git-scm.com/
* get sources:
```
git clone --recurse-submodules https://githomelab.ru/pykd/pykd.git local_dir
```
* open pykd.sln
* choose a python version and a target platform then build pykd projects
## Projects used pykd
[mona.py](https://github.com/corelan/mona)
the exploit writer's swiss army knife
[flare-dbg](https://github.com/fireeye/flare-dbg)
flare-dbg is a project meant to aid malware reverse engineers in rapidly developing debugger scripts.
[voltron](https://github.com/snare/voltron)
Voltron is an extensible debugger UI toolkit written in Python

View File

@ -1,66 +0,0 @@
# Pykd - not only python extension for WinDBG
## Purpose
This project can help to automate debugging and crash dump analysis using Python. It allows one to take the best from both worlds: the expressiveness and convenience of Python with the power of WinDbg!
## Why do I need this?
If you want to automate the debugger but dislike the WinDbg built-in script machine syntax it's time to try again using the handy and powerful Python language. Even if you don't want to create your own script, maybe some existing scripts will be of interest to you?
## Getting started
* You should have installed python. Supported python: 2.7, 3.5 - 3.9
* Install pykd with command: 'pip install pykd'
* Use windbg extension (bootstrapper) to run pykd with windbg
## Windbg extension (bootstarpper)
Use it to run pykd within windbg.
[Home Page](https://githomelab.ru/pykd/pykd-ext)
[Download](https://githomelab.ru/pykd/pykd-ext/wikis/Downloads)
## Releases
Just run 'pip install pykd' to install or 'pip install pykd --upgrade' to upgrade to the last version
[PyPi](https://pypi.org/project/pykd)
[All Releases](/../wikis/All Releases)
## Documentation
[Wiki Home](/../wikis/Home)
[User Manual](/../wikis/User Manual rus)
[API Reference](/../wikis/API Reference)
## Useful tools for pykd and WinDBG
[windbg-pack](https://githomelab.ru/pykd/windbg-pack)
Set of python scripts for WinDBG
[pykdwin](https://githomelab.ru/pykd/pykdwin)
A library with auxiliary modules for writing small pykd scripts and daily use.
[windbg-kernel](https://githomelab.ru/pykd/windbg-kernel)
Set of pykd script for kernel debugging
## How to build ?
* install VS 2017
https://visualstudio.microsoft.com/downloads/
* install cmake
https://cmake.org/
* install git
https://git-scm.com/
* get sources:
```
git clone --recurse-submodules https://githomelab.ru/pykd/pykd.git local_dir
```
* open pykd.sln
* choose a python version and a target platform then build pykd projects
## Projects used pykd
[mona.py](https://github.com/corelan/mona)
the exploit writer's swiss army knife
[flare-dbg](https://github.com/fireeye/flare-dbg)
flare-dbg is a project meant to aid malware reverse engineers in rapidly developing debugger scripts.
[voltron](https://github.com/snare/voltron)
Voltron is an extensible debugger UI toolkit written in Python

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +0,0 @@
## Introduction
### Step 1: Getting Started
It is best to use the automatic installer for installation. It will install pykd in the correct location and also install and register all necessary components.
If the installation completes without errors, it is time to get acquainted with pykd. To do this, start **WinDbg** and begin a debugging session (open a process, dump file, or establish a connection with a kernel debugger). Now, you can load pykd by running the following command:
```
.load pykd.pyd
```
If any errors occur during loading, WinDbg will display a message. The absence of any messages indicates that the extension has been successfully loaded.
Now, you can start working. Execute the following command:
```
!pycmd
```
After running this command, the debugger will enter user input mode. All user input will be processed by the Python interpreter.
```
0:000> !pycmd
Python 2.6.6 (r266:84297, Aug 24 2010, 18:13:38) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> print "Hello world!"
Hello world!
>>>
```
Now is a good time to get familiar with Python syntax if you havent already. Python is very easy to learn.
Let's recall some basic syntax of Python:
```
>>> def printHello():
... i = 0
... while i < 4:
... print "Hello #%d" % i
... i += 1
...
>>> printHello()
Hello #0
Hello #1
Hello #2
Hello #3
>>>
```
Note: The indentation of blocks is determined by leading spaces, which is a "signature" feature of Python. For now, this knowledge will be sufficient. Lets move on.
### Step 2: Accessing Registers
Any debugger should provide three basic capabilities: reading processor registers, reading memory, and controlling debugging mode. Lets start with registers. With **pykd**, this is quite simple:
```
>>> print hex(reg("eip"))
0x778ecb60
>>> print hex(reg("esp"))
0x1ef0e0
>>> print hex(reg("esp")+4)
0x1ef0e4
```
In this case, we use the **PYKD** function `reg`. It reads processor registers by name. A curious reader might ask: how do we use functions from **PYKD** without explicitly importing the module? In reality, the module must be imported. However, **PYKD** automatically does this when constructing the Python console.
Let's write a small example to check where the current instruction pointer is pointing:
```
>>> print findSymbol(reg("eip"))
ntdll!LdrpDoDebuggerBreak+30
```
The `findSymbol` function attempts to find a debug symbol for a given address. In this case, we see that the instruction pointer is at offset `0x30` within the function `LdrpDoDebuggerBreak`, which is located in the **ntdll** module. We can determine this because we have debugging information for **ntdll.dll** (the corresponding **pdb** file). If symbols are not displaying for some reason, check your symbol path settings in **WinDbg**.
### Step 3: Accessing Memory
**PYKD** provides a large set of functions for accessing memory, which can be divided into three categories:
#### 1. Reading values from memory:
- `ptrByte`
- `ptrWord`
- `ptrDWord`
- `ptrQWord`
There are other functions as well; the full set can be found in the **PYKD 0.2 API Reference**. All functions take an address as a parameter and return the value stored at that address.
#### 2. Reading arrays
- `loadBytes`
- `loadWords`
- `loadDWords`
- `loadQWords`
All functions take a pointer to the beginning of an array and its length in elements as parameters. They return a **list** object containing the array elements.
#### 3. Reading strings
- `loadCStr`
- `loadWStr`
These functions read **null-terminated** strings from memory and return Python strings.
Lets modify the previous example to display function arguments. We assume that the function follows the **stdcall** calling convention and that its parameters are addressed by the **ebp** register.
```
>>> def printFunc():
... print findSymbol( reg("eip") )
... params = [ ptrDWord( reg("ebp") + 4*(i+1) ) for i in range(0,3) ]
... print "var1: %x var2: %x var3: %x" % ( params[0], params[1], params[2] )
...
>>> print printFunc()
ntdll32!LdrpDoDebuggerBreak+2c
var1: 774b1383 var2: fffdd000 var3: fffde000
None
>>>
```
Pay attention to this construct:
```
params = [ ptrDWord( reg("ebp") + 4*(i+1) ) for i in range(0,3) ]
```
This is a **list comprehension**—a special Python construct that simplifies list initialization. It is equivalent to:
```
[ ptrDWord( reg("ebp") + 4) ), ptrDWord( reg("ebp") + 8) ), ptrDWord( reg("ebp") + 0xC) ) ]
```
### Step 4: Accessing Memory with Type Information
When debugging programs, we often work with **typed variables**. **PYKD** has powerful capabilities for accessing variables while preserving type information. This is one of the key features of the project: accessing struct and class fields in a way similar to source code.
For example, consider the following **C** code:
```
struct STRUCT_A {
int field1;
char field2;
};
STRUCT_A a = { 100, 2 }
```
Now, during debugging, we want to check the state of variable `a` using **PYKD**:
```
a = typedVar( "module!STRUCT_A", getOffset("module!a") )
if a.field1 != 100 or a.field2 != 2:
print "ERROR! a is not properly initialized!"
```

@ -1 +1 @@
Subproject commit 8d27b5bbe0ab88408076b688f0794c42cdafdf21 Subproject commit e54598d2f904acab23d340c93ce77c551a396ecb

292
pykd.sln
View File

@ -32,8 +32,11 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kdlib", "kdlibcpp\kdlib\source\kdlib.vcxproj", "{3E9C538F-F060-4E86-AB7D-D44439615B63}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kdlib", "kdlibcpp\kdlib\source\kdlib.vcxproj", "{3E9C538F-F060-4E86-AB7D-D44439615B63}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pykd", "pykd\pykd.vcxproj", "{C4C45791-0201-4406-BC5C-A384B01E3BF5}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pykd", "pykd\pykd.vcxproj", "{C4C45791-0201-4406-BC5C-A384B01E3BF5}"
ProjectSection(ProjectDependencies) = postProject
{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF} = {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pykd_ext_2.0", "pykd_ext\sources\pykd_ext.vcxproj", "{583F9A6C-AF6D-45E0-A8F4-290D93611185}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "targetapp", "kdlibcpp\kdlib\tests\targetapp\targetapp.vcxproj", "{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -41,12 +44,6 @@ Global
Debug_2.7|x64 = Debug_2.7|x64 Debug_2.7|x64 = Debug_2.7|x64
Debug_3.10|Win32 = Debug_3.10|Win32 Debug_3.10|Win32 = Debug_3.10|Win32
Debug_3.10|x64 = Debug_3.10|x64 Debug_3.10|x64 = Debug_3.10|x64
Debug_3.11|Win32 = Debug_3.11|Win32
Debug_3.11|x64 = Debug_3.11|x64
Debug_3.12|Win32 = Debug_3.12|Win32
Debug_3.12|x64 = Debug_3.12|x64
Debug_3.13|Win32 = Debug_3.13|Win32
Debug_3.13|x64 = Debug_3.13|x64
Debug_3.5|Win32 = Debug_3.5|Win32 Debug_3.5|Win32 = Debug_3.5|Win32
Debug_3.5|x64 = Debug_3.5|x64 Debug_3.5|x64 = Debug_3.5|x64
Debug_3.6|Win32 = Debug_3.6|Win32 Debug_3.6|Win32 = Debug_3.6|Win32
@ -61,12 +58,6 @@ Global
Release_2.7|x64 = Release_2.7|x64 Release_2.7|x64 = Release_2.7|x64
Release_3.10|Win32 = Release_3.10|Win32 Release_3.10|Win32 = Release_3.10|Win32
Release_3.10|x64 = Release_3.10|x64 Release_3.10|x64 = Release_3.10|x64
Release_3.11|Win32 = Release_3.11|Win32
Release_3.11|x64 = Release_3.11|x64
Release_3.12|Win32 = Release_3.12|Win32
Release_3.12|x64 = Release_3.12|x64
Release_3.13|Win32 = Release_3.13|Win32
Release_3.13|x64 = Release_3.13|x64
Release_3.5|Win32 = Release_3.5|Win32 Release_3.5|Win32 = Release_3.5|Win32
Release_3.5|x64 = Release_3.5|x64 Release_3.5|x64 = Release_3.5|x64
Release_3.6|Win32 = Release_3.6|Win32 Release_3.6|Win32 = Release_3.6|Win32
@ -84,12 +75,6 @@ Global
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_2.7|x64.ActiveCfg = Debug|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_2.7|x64.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.10|Win32.ActiveCfg = Debug|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.10|Win32.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.10|x64.ActiveCfg = Debug|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.10|x64.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.11|Win32.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.11|x64.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.12|Win32.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.12|x64.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.13|Win32.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.13|x64.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.5|Win32.ActiveCfg = Debug|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.5|Win32.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.5|x64.ActiveCfg = Debug|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.5|x64.ActiveCfg = Debug|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.6|Win32.ActiveCfg = Debug|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Debug_3.6|Win32.ActiveCfg = Debug|Any CPU
@ -104,12 +89,6 @@ Global
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_2.7|x64.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_2.7|x64.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.10|Win32.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.10|Win32.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.10|x64.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.10|x64.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.11|Win32.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.11|x64.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.12|Win32.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.12|x64.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.13|Win32.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.13|x64.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.5|Win32.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.5|Win32.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.5|x64.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.5|x64.ActiveCfg = Release|Any CPU
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.6|Win32.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.6|Win32.ActiveCfg = Release|Any CPU
@ -122,14 +101,8 @@ Global
{3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.9|x64.ActiveCfg = Release|Any CPU {3F0BE77E-19B0-4192-B432-44A25805BCB8}.Release_3.9|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_2.7|Win32.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_2.7|Win32.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_2.7|x64.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_2.7|x64.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.10|Win32.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.10|Win32.ActiveCfg = Debug_3.10|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.10|x64.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.10|x64.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.11|Win32.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.11|x64.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.12|Win32.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.12|x64.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.13|Win32.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.13|x64.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.5|Win32.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.5|Win32.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.5|x64.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.5|x64.ActiveCfg = Debug|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.6|Win32.ActiveCfg = Debug|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Debug_3.6|Win32.ActiveCfg = Debug|Any CPU
@ -144,12 +117,6 @@ Global
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_2.7|x64.ActiveCfg = Release|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_2.7|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.10|Win32.ActiveCfg = Release|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.10|Win32.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.10|x64.ActiveCfg = Release|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.10|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.11|Win32.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.11|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.12|Win32.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.12|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.13|Win32.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.13|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.5|Win32.ActiveCfg = Release|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.5|Win32.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.5|x64.ActiveCfg = Release|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.5|x64.ActiveCfg = Release|Any CPU
{6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.6|Win32.ActiveCfg = Release|Any CPU {6471FEDC-3129-410F-BFFC-4BC89707E5EC}.Release_3.6|Win32.ActiveCfg = Release|Any CPU
@ -164,12 +131,6 @@ Global
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_2.7|x64.ActiveCfg = Debug|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_2.7|x64.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.10|Win32.ActiveCfg = Debug|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.10|Win32.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.10|x64.ActiveCfg = Debug|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.10|x64.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.11|Win32.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.11|x64.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.12|Win32.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.12|x64.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.13|Win32.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.13|x64.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.5|Win32.ActiveCfg = Debug|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.5|Win32.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.5|x64.ActiveCfg = Debug|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.5|x64.ActiveCfg = Debug|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.6|Win32.ActiveCfg = Debug|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Debug_3.6|Win32.ActiveCfg = Debug|Any CPU
@ -184,12 +145,6 @@ Global
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_2.7|x64.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_2.7|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.10|Win32.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.10|Win32.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.10|x64.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.10|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.11|Win32.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.11|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.12|Win32.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.12|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.13|Win32.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.13|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.5|Win32.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.5|Win32.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.5|x64.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.5|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.6|Win32.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.6|Win32.ActiveCfg = Release|Any CPU
@ -200,46 +155,33 @@ Global
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.8|x64.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.8|x64.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.9|Win32.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.9|Win32.ActiveCfg = Release|Any CPU
{D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.9|x64.ActiveCfg = Release|Any CPU {D78837DC-BF31-4FC4-88A5-7F2FADAFA795}.Release_3.9|x64.ActiveCfg = Release|Any CPU
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|Win32.ActiveCfg = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|Win32.Build.0 = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|x64.Build.0 = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_2.7|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|Win32.ActiveCfg = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.10|x64.Build.0 = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|Win32.ActiveCfg = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.11|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|Win32.Build.0 = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.11|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.11|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.11|x64.Build.0 = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|Win32.ActiveCfg = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.12|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|Win32.Build.0 = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.12|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.12|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.12|x64.Build.0 = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|Win32.ActiveCfg = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.13|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|Win32.Build.0 = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.13|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.13|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.13|x64.Build.0 = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|Win32.ActiveCfg = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|Win32.Build.0 = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.5|x64.Build.0 = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|Win32.ActiveCfg = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|Win32.ActiveCfg = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|Win32.Build.0 = Debug|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|Win32.Build.0 = Debug_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|x64.ActiveCfg = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|x64.ActiveCfg = Debug_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|x64.Build.0 = Debug|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.6|x64.Build.0 = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|Win32.ActiveCfg = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|Win32.Build.0 = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|x64.ActiveCfg = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.7|x64.Build.0 = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|Win32.ActiveCfg = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|Win32.Build.0 = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|x64.ActiveCfg = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.8|x64.Build.0 = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|Win32.ActiveCfg = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|Win32.Build.0 = Debug_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|x64.ActiveCfg = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Debug_3.9|x64.Build.0 = Debug_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_2.7|Win32.ActiveCfg = Release_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_2.7|Win32.ActiveCfg = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_2.7|Win32.Build.0 = Release_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_2.7|Win32.Build.0 = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_2.7|x64.ActiveCfg = Release_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_2.7|x64.ActiveCfg = Release_Static|x64
@ -248,18 +190,6 @@ Global
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.10|Win32.Build.0 = Release_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.10|Win32.Build.0 = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.10|x64.ActiveCfg = Release_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.10|x64.ActiveCfg = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.10|x64.Build.0 = Release_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.10|x64.Build.0 = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.11|Win32.ActiveCfg = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.11|Win32.Build.0 = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.11|x64.ActiveCfg = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.11|x64.Build.0 = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.12|Win32.ActiveCfg = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.12|Win32.Build.0 = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.12|x64.ActiveCfg = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.12|x64.Build.0 = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.13|Win32.ActiveCfg = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.13|Win32.Build.0 = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.13|x64.ActiveCfg = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.13|x64.Build.0 = Release_Static|x64
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.5|Win32.ActiveCfg = Release_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.5|Win32.ActiveCfg = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.5|Win32.Build.0 = Release_Static|Win32 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.5|Win32.Build.0 = Release_Static|Win32
{3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.5|x64.ActiveCfg = Release_Static|x64 {3E9C538F-F060-4E86-AB7D-D44439615B63}.Release_3.5|x64.ActiveCfg = Release_Static|x64
@ -288,18 +218,6 @@ Global
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.10|Win32.Build.0 = Debug_3.10|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.10|Win32.Build.0 = Debug_3.10|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.10|x64.ActiveCfg = Debug_3.10|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.10|x64.ActiveCfg = Debug_3.10|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.10|x64.Build.0 = Debug_3.10|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.10|x64.Build.0 = Debug_3.10|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.11|Win32.ActiveCfg = Debug_3.11|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.11|Win32.Build.0 = Debug_3.11|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.11|x64.ActiveCfg = Debug_3.11|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.11|x64.Build.0 = Debug_3.11|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.12|Win32.ActiveCfg = Debug_3.12|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.12|Win32.Build.0 = Debug_3.12|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.12|x64.ActiveCfg = Debug_3.12|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.12|x64.Build.0 = Debug_3.12|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.13|Win32.ActiveCfg = Debug_3.13|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.13|Win32.Build.0 = Debug_3.13|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.13|x64.ActiveCfg = Debug_3.13|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.13|x64.Build.0 = Debug_3.13|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.5|Win32.ActiveCfg = Debug_3.5|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.5|Win32.ActiveCfg = Debug_3.5|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.5|Win32.Build.0 = Debug_3.5|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.5|Win32.Build.0 = Debug_3.5|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.5|x64.ActiveCfg = Debug_3.5|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Debug_3.5|x64.ActiveCfg = Debug_3.5|x64
@ -328,18 +246,6 @@ Global
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.10|Win32.Build.0 = Release_3.10|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.10|Win32.Build.0 = Release_3.10|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.10|x64.ActiveCfg = Release_3.10|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.10|x64.ActiveCfg = Release_3.10|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.10|x64.Build.0 = Release_3.10|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.10|x64.Build.0 = Release_3.10|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.11|Win32.ActiveCfg = Release_3.11|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.11|Win32.Build.0 = Release_3.11|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.11|x64.ActiveCfg = Release_3.11|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.11|x64.Build.0 = Release_3.11|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.12|Win32.ActiveCfg = Release_3.12|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.12|Win32.Build.0 = Release_3.12|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.12|x64.ActiveCfg = Release_3.12|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.12|x64.Build.0 = Release_3.12|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.13|Win32.ActiveCfg = Release_3.13|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.13|Win32.Build.0 = Release_3.13|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.13|x64.ActiveCfg = Release_3.13|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.13|x64.Build.0 = Release_3.13|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.5|Win32.ActiveCfg = Release_3.5|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.5|Win32.ActiveCfg = Release_3.5|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.5|Win32.Build.0 = Release_3.5|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.5|Win32.Build.0 = Release_3.5|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.5|x64.ActiveCfg = Release_3.5|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.5|x64.ActiveCfg = Release_3.5|x64
@ -360,86 +266,61 @@ Global
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.9|Win32.Build.0 = Release_3.9|Win32 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.9|Win32.Build.0 = Release_3.9|Win32
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.9|x64.ActiveCfg = Release_3.9|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.9|x64.ActiveCfg = Release_3.9|x64
{C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.9|x64.Build.0 = Release_3.9|x64 {C4C45791-0201-4406-BC5C-A384B01E3BF5}.Release_3.9|x64.Build.0 = Release_3.9|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_2.7|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_2.7|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_2.7|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_2.7|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_2.7|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_2.7|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_2.7|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_2.7|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.10|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.10|Win32.ActiveCfg = Debug_3.10|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.10|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.10|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.10|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.10|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.10|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.5|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.11|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.5|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.11|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.5|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.11|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.5|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.11|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.6|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.12|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.6|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.12|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.6|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.12|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.6|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.12|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.7|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.13|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.7|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.13|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.7|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.13|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.7|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.13|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.8|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.5|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.8|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.5|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.8|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.5|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.8|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.5|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.9|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.6|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.9|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.6|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.9|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.6|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Debug_3.9|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.6|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_2.7|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.7|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_2.7|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.7|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_2.7|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.7|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_2.7|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.7|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.10|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.8|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.10|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.8|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.10|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.8|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.10|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.8|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.5|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.9|Win32.ActiveCfg = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.5|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.9|Win32.Build.0 = Debug|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.5|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.9|x64.ActiveCfg = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.5|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Debug_3.9|x64.Build.0 = Debug|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.6|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_2.7|Win32.ActiveCfg = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.6|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_2.7|Win32.Build.0 = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.6|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_2.7|x64.ActiveCfg = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.6|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_2.7|x64.Build.0 = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.7|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.10|Win32.ActiveCfg = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.7|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.10|Win32.Build.0 = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.7|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.10|x64.ActiveCfg = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.7|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.10|x64.Build.0 = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.8|Win32.ActiveCfg = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.11|Win32.ActiveCfg = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.8|Win32.Build.0 = Debug|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.11|Win32.Build.0 = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.8|x64.ActiveCfg = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.11|x64.ActiveCfg = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.8|x64.Build.0 = Debug|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.11|x64.Build.0 = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.9|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.12|Win32.ActiveCfg = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.9|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.12|Win32.Build.0 = Release|Win32 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.9|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.12|x64.ActiveCfg = Release|x64 {0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF}.Release_3.9|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.12|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.13|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.13|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.13|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.13|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.5|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.5|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.5|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.5|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.6|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.6|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.6|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.6|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.7|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.7|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.7|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.7|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.8|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.8|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.8|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.8|x64.Build.0 = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.9|Win32.ActiveCfg = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.9|Win32.Build.0 = Release|Win32
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.9|x64.ActiveCfg = Release|x64
{583F9A6C-AF6D-45E0-A8F4-290D93611185}.Release_3.9|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -448,6 +329,7 @@ Global
{EEFC9510-DFA7-439E-801E-48FCE72766AD} = {A7AF87D2-983B-4B3A-823F-5A2C6989672E} {EEFC9510-DFA7-439E-801E-48FCE72766AD} = {A7AF87D2-983B-4B3A-823F-5A2C6989672E}
{3F0BE77E-19B0-4192-B432-44A25805BCB8} = {5A3C2DA6-AE91-4025-AC03-A58BD03CEBCD} {3F0BE77E-19B0-4192-B432-44A25805BCB8} = {5A3C2DA6-AE91-4025-AC03-A58BD03CEBCD}
{6471FEDC-3129-410F-BFFC-4BC89707E5EC} = {AAB21DD2-B0EE-493E-8415-5195F18879EB} {6471FEDC-3129-410F-BFFC-4BC89707E5EC} = {AAB21DD2-B0EE-493E-8415-5195F18879EB}
{0E4CC688-F2F5-499F-9C07-0F2CAEE0D3EF} = {5A3C2DA6-AE91-4025-AC03-A58BD03CEBCD}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {23D3DF9E-C3F8-476E-8B59-440641E1B2D6} SolutionGuid = {23D3DF9E-C3F8-476E-8B59-440641E1B2D6}

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "dict.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "errors.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "exec.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "import.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "list.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "long.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "module.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "object_operators.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "object_protocol.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "slice.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "str.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "tuple.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "wrapper.cpp"

View File

@ -0,0 +1,28 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/converter/arg_to_python_base.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/refcount.hpp>
namespace boost { namespace python { namespace converter {
namespace detail
{
arg_to_python_base::arg_to_python_base(
void const volatile* source, registration const& converters)
# if !defined(BOOST_MSVC) || BOOST_MSVC <= 1300 || _MSC_FULL_VER > 13102179
: handle<>
# else
: m_ptr
# endif
(converters.to_python(source))
{
}
}
}}} // namespace boost::python::converter

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "arg_to_python_base.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "builtin_converters.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "from_python.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "registry.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "type_id.cpp"

View File

@ -0,0 +1,592 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/handle.hpp>
#include <boost/python/type_id.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/refcount.hpp>
#include <boost/python/detail/config.hpp>
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/converter/builtin_converters.hpp>
#include <boost/python/converter/rvalue_from_python_data.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/converter/shared_ptr_deleter.hpp>
#include <boost/python/converter/pytype_function.hpp>
#include <boost/cast.hpp>
#include <string>
#include <complex>
namespace boost { namespace python { namespace converter {
shared_ptr_deleter::shared_ptr_deleter(handle<> owner)
: owner(owner)
{}
shared_ptr_deleter::~shared_ptr_deleter() {}
void shared_ptr_deleter::operator()(void const*)
{
owner.reset();
}
namespace
{
// An lvalue conversion function which extracts a char const* from a
// Python String.
#if PY_VERSION_HEX < 0x03000000
void* convert_to_cstring(PyObject* obj)
{
return PyString_Check(obj) ? PyString_AsString(obj) : 0;
}
#elif PY_VERSION_HEX < 0x03070000
void* convert_to_cstring(PyObject* obj)
{
return PyUnicode_Check(obj) ? _PyUnicode_AsString(obj) : 0;
}
#else
void* convert_to_cstring(PyObject* obj)
{
return PyUnicode_Check(obj) ? const_cast<void*>(reinterpret_cast<const void*>(_PyUnicode_AsString(obj))) : 0;
}
#endif
// Given a target type and a SlotPolicy describing how to perform a
// given conversion, registers from_python converters which use the
// SlotPolicy to extract the type.
template <class T, class SlotPolicy>
struct slot_rvalue_from_python
{
public:
slot_rvalue_from_python()
{
registry::insert(
&slot_rvalue_from_python<T,SlotPolicy>::convertible
, &slot_rvalue_from_python<T,SlotPolicy>::construct
, type_id<T>()
, &SlotPolicy::get_pytype
);
}
private:
static void* convertible(PyObject* obj)
{
unaryfunc* slot = SlotPolicy::get_slot(obj);
return slot && *slot ? slot : 0;
}
static void construct(PyObject* obj, rvalue_from_python_stage1_data* data)
{
// Get the (intermediate) source object
unaryfunc creator = *static_cast<unaryfunc*>(data->convertible);
handle<> intermediate(creator(obj));
// Get the location in which to construct
void* storage = ((rvalue_from_python_storage<T>*)data)->storage.bytes;
# ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4244)
# endif
new (storage) T( SlotPolicy::extract(intermediate.get()) );
# ifdef _MSC_VER
# pragma warning(pop)
# endif
// record successful construction
data->convertible = storage;
}
};
// identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
// "slot" which just returns its argument.
extern "C" PyObject* identity_unaryfunc(PyObject* x)
{
Py_INCREF(x);
return x;
}
unaryfunc py_object_identity = identity_unaryfunc;
#if PY_VERSION_HEX >= 0x03000000
// As in Python 3 there is only one integer type, we can have much
// simplified logic.
// XXX(bhy) maybe the code will work with 2.6 or even 2.5?
struct int_rvalue_from_python_base
{
static unaryfunc* get_slot(PyObject* obj)
{
return PyLong_Check(obj) ? &py_object_identity : 0;
}
static PyTypeObject const* get_pytype() {return &PyLong_Type;}
};
template <class T>
struct signed_int_rvalue_from_python : int_rvalue_from_python_base
{
static T extract(PyObject* intermediate)
{
long x = PyLong_AsLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(x);
}
};
template <class T>
struct unsigned_int_rvalue_from_python : int_rvalue_from_python_base
{
static T extract(PyObject* intermediate)
{
unsigned long x = PyLong_AsUnsignedLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(x);
}
};
#else // PY_VERSION_HEX >= 0x03000000
// A SlotPolicy for extracting signed integer types from Python objects
struct signed_int_rvalue_from_python_base
{
static unaryfunc* get_slot(PyObject* obj)
{
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0)
return 0;
return (
#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
!PyBool_Check(obj) &&
#endif
(PyInt_Check(obj) || PyLong_Check(obj)))
? &number_methods->nb_int : 0;
}
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
};
template <class T>
struct signed_int_rvalue_from_python : signed_int_rvalue_from_python_base
{
static T extract(PyObject* intermediate)
{
long x = PyInt_AsLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(x);
}
};
// A SlotPolicy for extracting unsigned integer types from Python objects
struct unsigned_int_rvalue_from_python_base
{
static unaryfunc* get_slot(PyObject* obj)
{
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0)
return 0;
return (
#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
!PyBool_Check(obj) &&
#endif
(PyInt_Check(obj) || PyLong_Check(obj)))
? &py_object_identity : 0;
}
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
};
template <class T>
struct unsigned_int_rvalue_from_python : unsigned_int_rvalue_from_python_base
{
static T extract(PyObject* intermediate)
{
if (PyLong_Check(intermediate)) {
// PyLong_AsUnsignedLong() checks for negative overflow, so no
// need to check it here.
unsigned long result = PyLong_AsUnsignedLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(result);
} else {
// None of PyInt_AsUnsigned*() functions check for negative
// overflow, so use PyInt_AS_LONG instead and check if number is
// negative, issuing the exception appropriately.
long result = PyInt_AS_LONG(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
if (result < 0) {
PyErr_SetString(PyExc_OverflowError, "can't convert negative"
" value to unsigned");
throw_error_already_set();
}
return numeric_cast<T>(result);
}
}
};
#endif // PY_VERSION_HEX >= 0x03000000
// Checking Python's macro instead of Boost's - we don't seem to get
// the config right all the time. Furthermore, Python's is defined
// when long long is absent but __int64 is present.
#ifdef HAVE_LONG_LONG
// A SlotPolicy for extracting long long types from Python objects
struct long_long_rvalue_from_python_base
{
static unaryfunc* get_slot(PyObject* obj)
{
#if PY_VERSION_HEX >= 0x03000000
return PyLong_Check(obj) ? &py_object_identity : 0;
#else
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0)
return 0;
// Return the identity conversion slot to avoid creating a
// new object. We'll handle that in the extract function
if (PyInt_Check(obj))
return &number_methods->nb_int;
else if (PyLong_Check(obj))
return &number_methods->nb_long;
else
return 0;
#endif
}
static PyTypeObject const* get_pytype() { return &PyLong_Type;}
};
struct long_long_rvalue_from_python : long_long_rvalue_from_python_base
{
static BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
{
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(intermediate))
{
return PyInt_AS_LONG(intermediate);
}
else
#endif
{
BOOST_PYTHON_LONG_LONG result = PyLong_AsLongLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
}
};
struct unsigned_long_long_rvalue_from_python : long_long_rvalue_from_python_base
{
static unsigned BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
{
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(intermediate))
{
return numeric_cast<unsigned BOOST_PYTHON_LONG_LONG>(PyInt_AS_LONG(intermediate));
}
else
#endif
{
unsigned BOOST_PYTHON_LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
}
};
#endif
// A SlotPolicy for extracting bool from a Python object
struct bool_rvalue_from_python
{
static unaryfunc* get_slot(PyObject* obj)
{
#if PY_VERSION_HEX >= 0x03000000
return obj == Py_None || PyLong_Check(obj) ? &py_object_identity : 0;
#elif PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
return obj == Py_None || PyBool_Check(obj) ? &py_object_identity : 0;
#else
return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0;
#endif
}
static bool extract(PyObject* intermediate)
{
return PyObject_IsTrue(intermediate);
}
static PyTypeObject const* get_pytype()
{
#if PY_VERSION_HEX >= 0x02030000
return &PyBool_Type;
#else
return &PyInt_Type;
#endif
}
};
// A SlotPolicy for extracting floating types from Python objects.
struct float_rvalue_from_python
{
static unaryfunc* get_slot(PyObject* obj)
{
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0)
return 0;
// For integer types, return the tp_int conversion slot to avoid
// creating a new object. We'll handle that below
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(obj))
return &number_methods->nb_int;
#endif
return (PyLong_Check(obj) || PyFloat_Check(obj))
? &number_methods->nb_float : 0;
}
static double extract(PyObject* intermediate)
{
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(intermediate))
{
return PyInt_AS_LONG(intermediate);
}
else
#endif
{
return PyFloat_AS_DOUBLE(intermediate);
}
}
static PyTypeObject const* get_pytype() { return &PyFloat_Type;}
};
#if PY_VERSION_HEX >= 0x03000000
unaryfunc py_unicode_as_string_unaryfunc = PyUnicode_AsUTF8String;
#endif
// A SlotPolicy for extracting C++ strings from Python objects.
struct string_rvalue_from_python
{
// If the underlying object is "string-able" this will succeed
static unaryfunc* get_slot(PyObject* obj)
{
#if PY_VERSION_HEX >= 0x03000000
return (PyUnicode_Check(obj)) ? &py_unicode_as_string_unaryfunc :
PyBytes_Check(obj) ? &py_object_identity : 0;
#else
return (PyString_Check(obj)) ? &obj->ob_type->tp_str : 0;
#endif
};
// Remember that this will be used to construct the result object
#if PY_VERSION_HEX >= 0x03000000
static std::string extract(PyObject* intermediate)
{
return std::string(PyBytes_AsString(intermediate),PyBytes_Size(intermediate));
}
static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
#else
static std::string extract(PyObject* intermediate)
{
return std::string(PyString_AsString(intermediate),PyString_Size(intermediate));
}
static PyTypeObject const* get_pytype() { return &PyString_Type;}
#endif
};
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
// encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc
// "slot" which encodes a Python string using the default encoding
extern "C" PyObject* encode_string_unaryfunc(PyObject* x)
{
return PyUnicode_FromEncodedObject( x, 0, 0 );
}
unaryfunc py_encode_string = encode_string_unaryfunc;
// A SlotPolicy for extracting C++ strings from Python objects.
struct wstring_rvalue_from_python
{
// If the underlying object is "string-able" this will succeed
static unaryfunc* get_slot(PyObject* obj)
{
return PyUnicode_Check(obj)
? &py_object_identity
#if PY_VERSION_HEX >= 0x03000000
: PyBytes_Check(obj)
#else
: PyString_Check(obj)
#endif
? &py_encode_string
: 0;
};
// Remember that this will be used to construct the result object
static std::wstring extract(PyObject* intermediate)
{
// On Windows, with Python >= 3.3, PyObject_Length cannot be used to get
// the size of the wchar_t string, because it will count the number of
// *code points*, but some characters not on the BMP will use two UTF-16
// *code units* (surrogate pairs).
// This is not a problem on Unix, since wchar_t is 32-bit.
#if defined(_WIN32) && PY_VERSION_HEX >= 0x03030000
BOOST_STATIC_ASSERT(sizeof(wchar_t) == 2);
Py_ssize_t size = 0;
wchar_t *buf = PyUnicode_AsWideCharString(intermediate, &size);
if (buf == NULL) {
boost::python::throw_error_already_set();
}
std::wstring result(buf, size);
PyMem_Free(buf);
#else
std::wstring result(::PyObject_Length(intermediate), L' ');
if (!result.empty())
{
int err = PyUnicode_AsWideChar(
#if PY_VERSION_HEX < 0x03020000
(PyUnicodeObject *)
#endif
intermediate
, &result[0]
, result.size());
if (err == -1)
throw_error_already_set();
}
#endif
return result;
}
static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
};
#endif
struct complex_rvalue_from_python
{
static unaryfunc* get_slot(PyObject* obj)
{
if (PyComplex_Check(obj))
return &py_object_identity;
else
return float_rvalue_from_python::get_slot(obj);
}
static std::complex<double> extract(PyObject* intermediate)
{
if (PyComplex_Check(intermediate))
{
return std::complex<double>(
PyComplex_RealAsDouble(intermediate)
, PyComplex_ImagAsDouble(intermediate));
}
#if PY_VERSION_HEX < 0x03000000
else if (PyInt_Check(intermediate))
{
return PyInt_AS_LONG(intermediate);
}
#endif
else
{
return PyFloat_AS_DOUBLE(intermediate);
}
}
static PyTypeObject const* get_pytype() { return &PyComplex_Type;}
};
}
BOOST_PYTHON_DECL PyObject* do_return_to_python(char x)
{
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_FromStringAndSize(&x, 1);
#else
return PyString_FromStringAndSize(&x, 1);
#endif
}
BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x)
{
#if PY_VERSION_HEX >= 0x03000000
return x ? PyUnicode_FromString(x) : boost::python::detail::none();
#else
return x ? PyString_FromString(x) : boost::python::detail::none();
#endif
}
BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x)
{
return x ? x : boost::python::detail::none();
}
BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject* x)
{
if (x == 0)
return boost::python::detail::none();
Py_INCREF(x);
return x;
}
#define REGISTER_INT_CONVERTERS(signedness, U) \
slot_rvalue_from_python< \
signedness U \
,signedness##_int_rvalue_from_python<signedness U> \
>()
#define REGISTER_INT_CONVERTERS2(U) \
REGISTER_INT_CONVERTERS(signed, U); \
REGISTER_INT_CONVERTERS(unsigned, U)
void initialize_builtin_converters()
{
// booleans
slot_rvalue_from_python<bool,bool_rvalue_from_python>();
// integer types
REGISTER_INT_CONVERTERS2(char);
REGISTER_INT_CONVERTERS2(short);
REGISTER_INT_CONVERTERS2(int);
REGISTER_INT_CONVERTERS2(long);
// using Python's macro instead of Boost's - we don't seem to get the
// config right all the time.
# ifdef HAVE_LONG_LONG
slot_rvalue_from_python<signed BOOST_PYTHON_LONG_LONG,long_long_rvalue_from_python>();
slot_rvalue_from_python<unsigned BOOST_PYTHON_LONG_LONG,unsigned_long_long_rvalue_from_python>();
# endif
// floating types
slot_rvalue_from_python<float,float_rvalue_from_python>();
slot_rvalue_from_python<double,float_rvalue_from_python>();
slot_rvalue_from_python<long double,float_rvalue_from_python>();
slot_rvalue_from_python<std::complex<float>,complex_rvalue_from_python>();
slot_rvalue_from_python<std::complex<double>,complex_rvalue_from_python>();
slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>();
// Add an lvalue converter for char which gets us char const*
#if PY_VERSION_HEX < 0x03000000
registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
#else
registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyUnicode_Type>::get_pytype);
#endif
// Register by-value converters to std::string, std::wstring
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();
# endif
slot_rvalue_from_python<std::string, string_rvalue_from_python>();
}
}}} // namespace boost::python::converter

View File

@ -0,0 +1,303 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/converter/from_python.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/converter/rvalue_from_python_data.hpp>
#include <boost/python/object/find_instance.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/detail/raw_pyobject.hpp>
#include <boost/python/cast.hpp>
#include <vector>
#include <algorithm>
namespace boost { namespace python { namespace converter {
// rvalue_from_python_stage1 -- do the first stage of a conversion
// from a Python object to a C++ rvalue.
//
// source - the Python object to be converted
// converters - the registry entry for the target type T
//
// Postcondition: where x is the result, one of:
//
// 1. x.convertible == 0, indicating failure
//
// 2. x.construct == 0, x.convertible is the address of an object of
// type T. Indicates a successful lvalue conversion
//
// 3. where y is of type rvalue_from_python_data<T>,
// x.construct(source, y) constructs an object of type T
// in y.storage.bytes and then sets y.convertible == y.storage.bytes,
// or else throws an exception and has no effect.
BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
PyObject* source
, registration const& converters)
{
rvalue_from_python_stage1_data data;
// First check to see if it's embedded in an extension class
// instance, as a special case.
data.convertible = objects::find_instance_impl(source, converters.target_type, converters.is_shared_ptr);
data.construct = 0;
if (!data.convertible)
{
for (rvalue_from_python_chain const* chain = converters.rvalue_chain;
chain != 0;
chain = chain->next)
{
void* r = chain->convertible(source);
if (r != 0)
{
data.convertible = r;
data.construct = chain->construct;
break;
}
}
}
return data;
}
// rvalue_result_from_python -- return the address of a C++ object which
// can be used as the result of calling a Python function.
//
// src - the Python object to be converted
//
// data - a reference to the base part of a
// rvalue_from_python_data<T> object, where T is the
// target type of the conversion.
//
// Requires: data.convertible == &registered<T>::converters
//
BOOST_PYTHON_DECL void* rvalue_result_from_python(
PyObject* src, rvalue_from_python_stage1_data& data)
{
// Retrieve the registration
// Cast in two steps for less-capable compilers
void const* converters_ = data.convertible;
registration const& converters = *static_cast<registration const*>(converters_);
// Look for an eligible converter
data = rvalue_from_python_stage1(src, converters);
return rvalue_from_python_stage2(src, data, converters);
}
BOOST_PYTHON_DECL void* rvalue_from_python_stage2(
PyObject* source, rvalue_from_python_stage1_data& data, registration const& converters)
{
if (!data.convertible)
{
handle<> msg(
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"No registered converter was able to produce a C++ rvalue of type %s from this Python object of type %s"
, converters.target_type.name()
, source->ob_type->tp_name
));
PyErr_SetObject(PyExc_TypeError, msg.get());
throw_error_already_set();
}
// If a construct function was registered (i.e. we found an
// rvalue conversion), call it now.
if (data.construct != 0)
data.construct(source, &data);
// Return the address of the resulting C++ object
return data.convertible;
}
BOOST_PYTHON_DECL void* get_lvalue_from_python(
PyObject* source
, registration const& converters)
{
// Check to see if it's embedded in a class instance
void* x = objects::find_instance_impl(source, converters.target_type);
if (x)
return x;
lvalue_from_python_chain const* chain = converters.lvalue_chain;
for (;chain != 0; chain = chain->next)
{
void* r = chain->convert(source);
if (r != 0)
return r;
}
return 0;
}
namespace
{
// Prevent looping in implicit conversions. This could/should be
// much more efficient, but will work for now.
typedef std::vector<rvalue_from_python_chain const*> visited_t;
static visited_t visited;
inline bool visit(rvalue_from_python_chain const* chain)
{
visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain);
if (p != visited.end() && *p == chain)
return false;
visited.insert(p, chain);
return true;
}
// RAII class for managing global visited marks.
struct unvisit
{
unvisit(rvalue_from_python_chain const* chain)
: chain(chain) {}
~unvisit()
{
visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain);
assert(p != visited.end());
visited.erase(p);
}
private:
rvalue_from_python_chain const* chain;
};
}
BOOST_PYTHON_DECL bool implicit_rvalue_convertible_from_python(
PyObject* source
, registration const& converters)
{
if (objects::find_instance_impl(source, converters.target_type))
return true;
rvalue_from_python_chain const* chain = converters.rvalue_chain;
if (!visit(chain))
return false;
unvisit protect(chain);
for (;chain != 0; chain = chain->next)
{
if (chain->convertible(source))
return true;
}
return false;
}
namespace
{
void throw_no_lvalue_from_python(PyObject* source, registration const& converters, char const* ref_type)
{
handle<> msg(
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"No registered converter was able to extract a C++ %s to type %s"
" from this Python object of type %s"
, ref_type
, converters.target_type.name()
, source->ob_type->tp_name
));
PyErr_SetObject(PyExc_TypeError, msg.get());
throw_error_already_set();
}
void* lvalue_result_from_python(
PyObject* source
, registration const& converters
, char const* ref_type)
{
handle<> holder(source);
if (source->ob_refcnt <= 1)
{
handle<> msg(
#if PY_VERSION_HEX >= 0x3000000
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"Attempt to return dangling %s to object of type: %s"
, ref_type
, converters.target_type.name()));
PyErr_SetObject(PyExc_ReferenceError, msg.get());
throw_error_already_set();
}
void* result = get_lvalue_from_python(source, converters);
if (!result)
(throw_no_lvalue_from_python)(source, converters, ref_type);
return result;
}
}
BOOST_PYTHON_DECL void throw_no_pointer_from_python(PyObject* source, registration const& converters)
{
(throw_no_lvalue_from_python)(source, converters, "pointer");
}
BOOST_PYTHON_DECL void throw_no_reference_from_python(PyObject* source, registration const& converters)
{
(throw_no_lvalue_from_python)(source, converters, "reference");
}
BOOST_PYTHON_DECL void* reference_result_from_python(
PyObject* source
, registration const& converters)
{
return (lvalue_result_from_python)(source, converters, "reference");
}
BOOST_PYTHON_DECL void* pointer_result_from_python(
PyObject* source
, registration const& converters)
{
if (source == Py_None)
{
Py_DECREF(source);
return 0;
}
return (lvalue_result_from_python)(source, converters, "pointer");
}
BOOST_PYTHON_DECL void void_result_from_python(PyObject* o)
{
Py_DECREF(expect_non_null(o));
}
} // namespace boost::python::converter
BOOST_PYTHON_DECL PyObject*
pytype_check(PyTypeObject* type_, PyObject* source)
{
if (!PyObject_IsInstance(source, python::upcast<PyObject>(type_)))
{
::PyErr_Format(
PyExc_TypeError
, "Expecting an object of type %s; got an object of type %s instead"
, type_->tp_name
, source->ob_type->tp_name
);
throw_error_already_set();
}
return source;
}
}} // namespace boost::python

View File

@ -0,0 +1,306 @@
// Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/converter/builtin_converters.hpp>
#include <set>
#include <stdexcept>
#if defined(__APPLE__) && defined(__MACH__) && defined(__GNUC__) \
&& __GNUC__ == 3 && __GNUC_MINOR__ <= 4 && !defined(__APPLE_CC__)
# define BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
#endif
#if defined(BOOST_PYTHON_TRACE_REGISTRY) \
|| defined(BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND)
# include <iostream>
#endif
namespace boost { namespace python { namespace converter {
BOOST_PYTHON_DECL PyTypeObject const* registration::expected_from_python_type() const
{
if (this->m_class_object != 0)
return this->m_class_object;
std::set<PyTypeObject const*> pool;
for(rvalue_from_python_chain* r = rvalue_chain; r ; r=r->next)
if(r->expected_pytype)
pool.insert(r->expected_pytype());
//for now I skip the search for common base
if (pool.size()==1)
return *pool.begin();
return 0;
}
BOOST_PYTHON_DECL PyTypeObject const* registration::to_python_target_type() const
{
if (this->m_class_object != 0)
return this->m_class_object;
if (this->m_to_python_target_type != 0)
return this->m_to_python_target_type();
return 0;
}
BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const
{
if (this->m_class_object == 0)
{
::PyErr_Format(
PyExc_TypeError
, const_cast<char*>("No Python class registered for C++ class %s")
, this->target_type.name());
throw_error_already_set();
}
return this->m_class_object;
}
BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source) const
{
if (this->m_to_python == 0)
{
handle<> msg(
#if PY_VERSION_HEX >= 0x3000000
::PyUnicode_FromFormat
#else
::PyString_FromFormat
#endif
(
"No to_python (by-value) converter found for C++ type: %s"
, this->target_type.name()
)
);
PyErr_SetObject(PyExc_TypeError, msg.get());
throw_error_already_set();
}
return source == 0
? incref(Py_None)
: this->m_to_python(const_cast<void*>(source));
}
namespace
{
template< typename T >
void delete_node( T* node )
{
if( !!node && !!node->next )
delete_node( node->next );
delete node;
}
}
registration::~registration()
{
delete_node(lvalue_chain);
delete_node(rvalue_chain);
}
namespace // <unnamed>
{
typedef registration entry;
typedef std::set<entry> registry_t;
#ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
registry_t& entries()
{
static registry_t registry;
# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
static bool builtin_converters_initialized = false;
if (!builtin_converters_initialized)
{
// Make this true early because registering the builtin
// converters will cause recursion.
builtin_converters_initialized = true;
initialize_builtin_converters();
}
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "registry: ";
for (registry_t::iterator p = registry.begin(); p != registry.end(); ++p)
{
std::cout << p->target_type << "; ";
}
std::cout << '\n';
# endif
# endif
return registry;
}
#else
registry_t& static_registry()
{
static registry_t result;
return result;
}
bool static_builtin_converters_initialized()
{
static bool result = false;
if (result == false) {
result = true;
std::cout << std::flush;
return false;
}
return true;
}
registry_t& entries()
{
# ifndef BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
if (!static_builtin_converters_initialized())
{
initialize_builtin_converters();
}
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "registry: ";
for (registry_t::iterator p = static_registry().begin(); p != static_registry().end(); ++p)
{
std::cout << p->target_type << "; ";
}
std::cout << '\n';
# endif
# endif
return static_registry();
}
#endif // BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
entry* get(type_info type, bool is_shared_ptr = false)
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
registry_t::iterator p = entries().find(entry(type));
std::cout << "looking up " << type << ": "
<< (p == entries().end() || p->target_type != type
? "...NOT found\n" : "...found\n");
# endif
std::pair<registry_t::const_iterator,bool> pos_ins
= entries().insert(entry(type,is_shared_ptr));
# if __MWERKS__ >= 0x3000
// do a little invariant checking if a change was made
if ( pos_ins.second )
assert(entries().invariants());
# endif
return const_cast<entry*>(&*pos_ins.first);
}
} // namespace <unnamed>
namespace registry
{
void insert(to_python_function_t f, type_info source_t, PyTypeObject const* (*to_python_target_type)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "inserting to_python " << source_t << "\n";
# endif
entry* slot = get(source_t);
assert(slot->m_to_python == 0); // we have a problem otherwise
if (slot->m_to_python != 0)
{
std::string msg = (
std::string("to-Python converter for ")
+ source_t.name()
+ " already registered; second conversion method ignored."
);
if ( ::PyErr_Warn( NULL, const_cast<char*>(msg.c_str()) ) )
{
throw_error_already_set();
}
}
slot->m_to_python = f;
slot->m_to_python_target_type = to_python_target_type;
}
// Insert an lvalue from_python converter
void insert(convertible_function convert, type_info key, PyTypeObject const* (*exp_pytype)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "inserting lvalue from_python " << key << "\n";
# endif
entry* found = get(key);
lvalue_from_python_chain *registration = new lvalue_from_python_chain;
registration->convert = convert;
registration->next = found->lvalue_chain;
found->lvalue_chain = registration;
insert(convert, 0, key,exp_pytype);
}
// Insert an rvalue from_python converter
void insert(convertible_function convertible
, constructor_function construct
, type_info key
, PyTypeObject const* (*exp_pytype)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "inserting rvalue from_python " << key << "\n";
# endif
entry* found = get(key);
rvalue_from_python_chain *registration = new rvalue_from_python_chain;
registration->convertible = convertible;
registration->construct = construct;
registration->expected_pytype = exp_pytype;
registration->next = found->rvalue_chain;
found->rvalue_chain = registration;
}
// Insert an rvalue from_python converter
void push_back(convertible_function convertible
, constructor_function construct
, type_info key
, PyTypeObject const* (*exp_pytype)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "push_back rvalue from_python " << key << "\n";
# endif
rvalue_from_python_chain** found = &get(key)->rvalue_chain;
while (*found != 0)
found = &(*found)->next;
rvalue_from_python_chain *registration = new rvalue_from_python_chain;
registration->convertible = convertible;
registration->construct = construct;
registration->expected_pytype = exp_pytype;
registration->next = 0;
*found = registration;
}
registration const& lookup(type_info key)
{
return *get(key);
}
registration const& lookup_shared_ptr(type_info key)
{
return *get(key, true);
}
registration const* query(type_info type)
{
registry_t::iterator p = entries().find(entry(type));
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "querying " << type
<< (p == entries().end() || p->target_type != type
? "...NOT found\n" : "...found\n");
# endif
return (p == entries().end() || p->target_type != type) ? 0 : &*p;
}
} // namespace registry
}}} // namespace boost::python::converter

View File

@ -0,0 +1,212 @@
// Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/type_id.hpp>
#include <boost/python/detail/decorated_type_id.hpp>
#include <utility>
#include <vector>
#include <algorithm>
#include <memory>
#include <cstdlib>
#include <cstring>
#if defined(__QNXNTO__)
# include <ostream>
#else /* defined(__QNXNTO__) */
#if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT || __EDG_VERSION__
# include <ostream>
#else
# include <ostream.h>
#endif
# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# if defined(__GNUC__) && __GNUC__ >= 3
// http://lists.debian.org/debian-gcc/2003/09/msg00055.html notes
// that, in cxxabi.h of gcc-3.x for x < 4, this type is used before it
// is declared.
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
class __class_type_info;
# endif
# include <cxxabi.h>
# endif
# endif
#endif /* defined(__QNXNTO__) */
namespace boost { namespace python {
# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
# if defined(__QNXNTO__)
namespace cxxabi {
extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
}
# else /* defined(__QNXNTO__) */
# ifdef __GNUC__
# if __GNUC__ < 3
namespace cxxabi = :: ;
extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
# else
namespace cxxabi = ::abi; // GCC 3.1 and later
# if __GNUC__ == 3 && __GNUC_MINOR__ == 0
namespace abi
{
extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
}
# endif /* __GNUC__ == 3 && __GNUC_MINOR__ == 0 */
# endif /* __GNUC__ < 3 */
# endif /* __GNUC__ */
# endif /* defined(__QNXNTO__) */
namespace
{
struct compare_first_cstring
{
template <class T>
bool operator()(T const& x, T const& y)
{
return std::strcmp(x.first,y.first) < 0;
}
};
struct free_mem
{
free_mem(char*p)
: p(p) {}
~free_mem()
{
std::free(p);
}
char* p;
};
}
bool cxxabi_cxa_demangle_is_broken()
{
static bool was_tested = false;
static bool is_broken = false;
if (!was_tested) {
int status;
free_mem keeper(cxxabi::__cxa_demangle("b", 0, 0, &status));
was_tested = true;
if (status == -2 || strcmp(keeper.p, "bool") != 0) {
is_broken = true;
}
}
return is_broken;
}
namespace detail
{
BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled)
{
typedef std::vector<
std::pair<char const*, char const*>
> mangling_map;
static mangling_map demangler;
mangling_map::iterator p
= std::lower_bound(
demangler.begin(), demangler.end()
, std::make_pair(mangled, (char const*)0)
, compare_first_cstring());
if (p == demangler.end() || strcmp(p->first, mangled))
{
int status;
free_mem keeper(
cxxabi::__cxa_demangle(mangled, 0, 0, &status)
);
assert(status != -3); // invalid argument error
if (status == -1)
{
throw std::bad_alloc();
}
else
{
char const* demangled
= status == -2
// Invalid mangled name. Best we can do is to
// return it intact.
? mangled
: keeper.p;
// Ult Mundane, 2005 Aug 17
// Contributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// The __cxa_demangle function is supposed to translate
// builtin types from their one-character mangled names,
// but it doesn't in gcc 3.3.5 and gcc 3.4.x.
if (cxxabi_cxa_demangle_is_broken()
&& status == -2 && strlen(mangled) == 1)
{
// list from
// http://www.codesourcery.com/cxx-abi/abi.html
switch (mangled[0])
{
case 'v': demangled = "void"; break;
case 'w': demangled = "wchar_t"; break;
case 'b': demangled = "bool"; break;
case 'c': demangled = "char"; break;
case 'a': demangled = "signed char"; break;
case 'h': demangled = "unsigned char"; break;
case 's': demangled = "short"; break;
case 't': demangled = "unsigned short"; break;
case 'i': demangled = "int"; break;
case 'j': demangled = "unsigned int"; break;
case 'l': demangled = "long"; break;
case 'm': demangled = "unsigned long"; break;
case 'x': demangled = "long long"; break;
case 'y': demangled = "unsigned long long"; break;
case 'n': demangled = "__int128"; break;
case 'o': demangled = "unsigned __int128"; break;
case 'f': demangled = "float"; break;
case 'd': demangled = "double"; break;
case 'e': demangled = "long double"; break;
case 'g': demangled = "__float128"; break;
case 'z': demangled = "..."; break;
}
}
p = demangler.insert(p, std::make_pair(mangled, demangled));
keeper.p = 0;
}
}
return p->second;
}
}
# endif
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_info const& x)
{
return os << x.name();
}
namespace detail
{
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, detail::decorated_type_info const& x)
{
os << x.m_base_type;
if (x.m_decoration & decorated_type_info::const_)
os << " const";
if (x.m_decoration & decorated_type_info::volatile_)
os << " volatile";
if (x.m_decoration & decorated_type_info::reference)
os << "&";
return os;
}
}
}} // namespace boost::python::converter

184
pykd/boost.python/dict.cpp Normal file
View File

@ -0,0 +1,184 @@
// Copyright David Abrahams 2004. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/dict.hpp>
#include <boost/python/extract.hpp>
namespace boost { namespace python { namespace detail {
namespace
{
// When returning list objects from methods, it may turn out that the
// derived class is returning something else, perhaps something not
// even derived from list. Since it is generally harmless for a
// Boost.Python wrapper object to hold an object of a different
// type, and because calling list() with an object may in fact
// perform a conversion, the least-bad alternative is to assume that
// we have a Python list object and stuff it into the list result.
list assume_list(object const& o)
{
return list(detail::borrowed_reference(o.ptr()));
}
// No PyDict_CheckExact; roll our own.
inline bool check_exact(dict_base const* p)
{
return p->ptr()->ob_type == &PyDict_Type;
}
}
detail::new_reference dict_base::call(object const& arg_)
{
return (detail::new_reference)PyObject_CallFunction(
(PyObject*)&PyDict_Type, const_cast<char*>("(O)"),
arg_.ptr());
}
dict_base::dict_base()
: object(detail::new_reference(PyDict_New()))
{}
dict_base::dict_base(object_cref data)
: object(call(data))
{}
void dict_base::clear()
{
if (check_exact(this))
PyDict_Clear(this->ptr());
else
this->attr("clear")();
}
dict dict_base::copy()
{
if (check_exact(this))
{
return dict(detail::new_reference(
PyDict_Copy(this->ptr())));
}
else
{
return dict(detail::borrowed_reference(
this->attr("copy")().ptr()
));
}
}
object dict_base::get(object_cref k) const
{
if (check_exact(this))
{
PyObject* result = PyDict_GetItem(this->ptr(),k.ptr());
return object(detail::borrowed_reference(result ? result : Py_None));
}
else
{
return this->attr("get")(k);
}
}
object dict_base::get(object_cref k, object_cref d) const
{
return this->attr("get")(k,d);
}
bool dict_base::has_key(object_cref k) const
{
return extract<bool>(this->contains(k));
}
list dict_base::items() const
{
if (check_exact(this))
{
return list(detail::new_reference(
PyDict_Items(this->ptr())));
}
else
{
return assume_list(this->attr("items")());
}
}
object dict_base::iteritems() const
{
return this->attr("iteritems")();
}
object dict_base::iterkeys() const
{
return this->attr("iterkeys")();
}
object dict_base::itervalues() const
{
return this->attr("itervalues")();
}
list dict_base::keys() const
{
if (check_exact(this))
{
return list(detail::new_reference(
PyDict_Keys(this->ptr())));
}
else
{
return assume_list(this->attr("keys")());
}
}
tuple dict_base::popitem()
{
return tuple(detail::borrowed_reference(
this->attr("popitem")().ptr()
));
}
object dict_base::setdefault(object_cref k)
{
return this->attr("setdefault")(k);
}
object dict_base::setdefault(object_cref k, object_cref d)
{
return this->attr("setdefault")(k,d);
}
void dict_base::update(object_cref other)
{
if (check_exact(this))
{
if (PyDict_Update(this->ptr(),other.ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("update")(other);
}
}
list dict_base::values() const
{
if (check_exact(this))
{
return list(detail::new_reference(
PyDict_Values(this->ptr())));
}
else
{
return assume_list(this->attr("values")());
}
}
static struct register_dict_pytype_ptr
{
register_dict_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::dict>())
).m_class_object = &PyDict_Type;
}
}register_dict_pytype_ptr_;
}}} // namespace boost::python

View File

@ -0,0 +1,105 @@
// Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PYTHON_SOURCE
# define BOOST_PYTHON_SOURCE
#endif
#include <boost/python/errors.hpp>
#include <boost/cast.hpp>
#include <boost/python/detail/exception_handler.hpp>
namespace boost { namespace python {
error_already_set::~error_already_set() {}
// IMPORTANT: this function may only be called from within a catch block!
BOOST_PYTHON_DECL bool handle_exception_impl(function0<void> f)
{
try
{
if (detail::exception_handler::chain)
return detail::exception_handler::chain->handle(f);
f();
return false;
}
catch(const boost::python::error_already_set&)
{
// The python error reporting has already been handled.
}
catch(const std::bad_alloc&)
{
PyErr_NoMemory();
}
catch(const bad_numeric_cast& x)
{
PyErr_SetString(PyExc_OverflowError, x.what());
}
catch(const std::out_of_range& x)
{
PyErr_SetString(PyExc_IndexError, x.what());
}
catch(const std::invalid_argument& x)
{
PyErr_SetString(PyExc_ValueError, x.what());
}
catch(const std::exception& x)
{
PyErr_SetString(PyExc_RuntimeError, x.what());
}
catch(...)
{
PyErr_SetString(PyExc_RuntimeError, "unidentifiable C++ exception");
}
return true;
}
void BOOST_PYTHON_DECL throw_error_already_set()
{
throw error_already_set();
}
namespace detail {
bool exception_handler::operator()(function0<void> const& f) const
{
if (m_next)
{
return m_next->handle(f);
}
else
{
f();
return false;
}
}
exception_handler::exception_handler(handler_function const& impl)
: m_impl(impl)
, m_next(0)
{
if (chain != 0)
tail->m_next = this;
else
chain = this;
tail = this;
}
exception_handler* exception_handler::chain;
exception_handler* exception_handler::tail;
BOOST_PYTHON_DECL void register_exception_handler(handler_function const& f)
{
// the constructor links the new object into a handler chain, so
// this object isn't actaully leaked (until, of course, the
// interpreter exits).
new exception_handler(f);
}
} // namespace boost::python::detail
}} // namespace boost::python

133
pykd/boost.python/exec.cpp Normal file
View File

@ -0,0 +1,133 @@
// Copyright Stefan Seefeld 2005.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/exec.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/handle.hpp>
namespace boost
{
namespace python
{
object BOOST_PYTHON_DECL eval(str string, object global, object local)
{
return eval(python::extract<char const *>(string), global, local);
}
object BOOST_PYTHON_DECL eval(char const *string, object global, object local)
{
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = const_cast<char *>(string);
PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
object BOOST_PYTHON_DECL exec(str string, object global, object local)
{
return exec(python::extract<char const *>(string), global, local);
}
object BOOST_PYTHON_DECL exec(char const *string, object global, object local)
{
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = const_cast<char *>(string);
PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
object BOOST_PYTHON_DECL exec_statement(str string, object global, object local)
{
return exec_statement(python::extract<char const *>(string), global, local);
}
object BOOST_PYTHON_DECL exec_statement(char const *string, object global, object local)
{
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = const_cast<char *>(string);
PyObject* result = PyRun_String(s, Py_single_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
// Execute python source code from file filename.
// global and local are the global and local scopes respectively,
// used during execution.
object BOOST_PYTHON_DECL exec_file(str filename, object global, object local)
{
return exec_file(python::extract<char const *>(filename), global, local);
}
object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object local)
{
// Set suitable default values for global and local dicts.
if (global.is_none())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.is_none()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *f = const_cast<char *>(filename);
// Let python open the file to avoid potential binary incompatibilities.
#if PY_VERSION_HEX >= 0x030a0000
PyObject* fo = Py_BuildValue("s", f);
FILE* fs = _Py_fopen_obj(fo, "r");
Py_DECREF(fo);
#elif PY_VERSION_HEX >= 0x03040000
FILE *fs = _Py_fopen(f, "r");
#elif PY_VERSION_HEX >= 0x03000000
PyObject *fo = Py_BuildValue("s", f);
FILE *fs = _Py_fopen(fo, "r");
Py_DECREF(fo);
#else
PyObject *pyfile = PyFile_FromString(f, const_cast<char*>("r"));
if (!pyfile) throw std::invalid_argument(std::string(f) + " : no such file");
python::handle<> file(pyfile);
FILE *fs = PyFile_AsFile(file.get());
#endif
PyObject* result = PyRun_File(fs,
f,
Py_file_input,
global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
} // namespace boost::python
} // namespace boost

View File

@ -0,0 +1,58 @@
# -*- python -*-
#
# Copyright (c) 2016 Stefan Seefeld
# All rights reserved.
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
from faber.feature import set
from faber.artefacts.library import library
from faber.tools.compiler import define
root = module('..')
bpl = library('boost_python' + root.py_suffix,
['list.cpp',
'long.cpp',
'dict.cpp',
'tuple.cpp',
'str.cpp',
'slice.cpp',
'converter/from_python.cpp',
'converter/registry.cpp',
'converter/type_id.cpp',
'object/enum.cpp',
'object/class.cpp',
'object/function.cpp',
'object/inheritance.cpp',
'object/life_support.cpp',
'object/pickle_support.cpp',
'errors.cpp',
'module.cpp',
'converter/builtin_converters.cpp',
'converter/arg_to_python_base.cpp',
'object/iterator.cpp',
'object/stl_iterator.cpp',
'object_protocol.cpp',
'object_operators.cpp',
'wrapper.cpp',
'import.cpp',
'exec.cpp',
'object/function_doc_signature.cpp'],
dependencies=root.config,
features=features + define('BOOST_PYTHON_SOURCE'))
bnl = library('boost_numpy' + root.py_suffix,
['numpy/dtype.cpp',
'numpy/matrix.cpp',
'numpy/ndarray.cpp',
'numpy/numpy.cpp',
'numpy/scalars.cpp',
'numpy/ufunc.cpp',
bpl],
dependencies=root.config,
features=features + define('BOOST_NUMPY_SOURCE'),
condition=set.define.contains('HAS_NUMPY'))
default = [bpl, bnl]

View File

@ -0,0 +1,25 @@
// Copyright Stefan Seefeld 2005.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/import.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/handle.hpp>
namespace boost
{
namespace python
{
object BOOST_PYTHON_DECL import(str name)
{
// should be 'char const *' but older python versions don't use 'const' yet.
char *n = python::extract<char *>(name);
python::handle<> module(PyImport_ImportModule(n));
return python::object(module);
}
} // namespace boost::python
} // namespace boost

170
pykd/boost.python/list.cpp Normal file
View File

@ -0,0 +1,170 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/list.hpp>
#include <boost/python/ssize_t.hpp>
namespace boost { namespace python { namespace detail {
detail::new_non_null_reference list_base::call(object const& arg_)
{
return (detail::new_non_null_reference)
(expect_non_null)(
PyObject_CallFunction(
(PyObject*)&PyList_Type, const_cast<char*>("(O)"),
arg_.ptr()));
}
list_base::list_base()
: object(detail::new_reference(PyList_New(0)))
{}
list_base::list_base(object_cref sequence)
: object(list_base::call(sequence))
{}
void list_base::append(object_cref x)
{
if (PyList_CheckExact(this->ptr()))
{
if (PyList_Append(this->ptr(), x.ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("append")(x);
}
}
//long list_base::count(object_cref value) const;
void list_base::extend(object_cref sequence)
{
this->attr("extend")(sequence);
}
long list_base::index(object_cref value) const
{
object result_obj(this->attr("index")(value));
#if PY_VERSION_HEX >= 0x03000000
ssize_t result = PyLong_AsSsize_t(result_obj.ptr());
#else
long result = PyInt_AsLong(result_obj.ptr());
#endif
if (result == -1)
throw_error_already_set();
return result;
}
void list_base::insert(ssize_t index, object_cref item)
{
if (PyList_CheckExact(this->ptr()))
{
if (PyList_Insert(this->ptr(), index, item.ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("insert")(index, item);
}
}
void list_base::insert(object const& index, object_cref x)
{
#if PY_VERSION_HEX >= 0x03000000
ssize_t index_ = PyLong_AsSsize_t(index.ptr());
#else
long index_ = PyInt_AsLong(index.ptr());
#endif
if (index_ == -1 && PyErr_Occurred())
throw_error_already_set();
this->insert(index_, x);
}
object list_base::pop()
{
return this->attr("pop")();
}
object list_base::pop(ssize_t index)
{
return this->pop(object(index));
}
object list_base::pop(object const& index)
{
return this->attr("pop")(index);
}
void list_base::remove(object_cref value)
{
this->attr("remove")(value);
}
void list_base::reverse()
{
if (PyList_CheckExact(this->ptr()))
{
if (PyList_Reverse(this->ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("reverse")();
}
}
void list_base::sort()
{
if (PyList_CheckExact(this->ptr()))
{
if (PyList_Sort(this->ptr()) == -1)
throw_error_already_set();
}
else
{
this->attr("sort")();
}
}
#if PY_VERSION_HEX >= 0x03000000
void list_base::sort(args_proxy const &args,
kwds_proxy const &kwds)
{
this->attr("sort")(args, kwds);
}
#else
void list_base::sort(object_cref cmpfunc)
{
this->attr("sort")(cmpfunc);
}
#endif
// For some reason, moving this to the end of the TU suppresses an ICE
// with vc6.
ssize_t list_base::count(object_cref value) const
{
object result_obj(this->attr("count")(value));
#if PY_VERSION_HEX >= 0x03000000
ssize_t result = PyLong_AsSsize_t(result_obj.ptr());
#else
long result = PyInt_AsLong(result_obj.ptr());
#endif
if (result == -1)
throw_error_already_set();
return result;
}
static struct register_list_pytype_ptr
{
register_list_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::list>())
).m_class_object = &PyList_Type;
}
}register_list_pytype_ptr_;
}}} // namespace boost::python

View File

@ -0,0 +1,39 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/long.hpp>
namespace boost { namespace python { namespace detail {
new_non_null_reference long_base::call(object const& arg_)
{
return (detail::new_non_null_reference)PyObject_CallFunction(
(PyObject*)&PyLong_Type, const_cast<char*>("(O)"),
arg_.ptr());
}
new_non_null_reference long_base::call(object const& arg_, object const& base)
{
return (detail::new_non_null_reference)PyObject_CallFunction(
(PyObject*)&PyLong_Type, const_cast<char*>("(OO)"),
arg_.ptr(), base.ptr());
}
long_base::long_base()
: object(
detail::new_reference(
PyObject_CallFunction((PyObject*)&PyLong_Type, const_cast<char*>("()")))
)
{}
long_base::long_base(object_cref arg)
: object(long_base::call(arg))
{}
long_base::long_base(object_cref arg, object_cref base)
: object(long_base::call(arg, base))
{}
}}} // namespace boost::python

View File

@ -0,0 +1,73 @@
// (C) Copyright David Abrahams 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
// producing this work.
#include <boost/python/scope.hpp>
#include <boost/python/object/add_to_namespace.hpp>
namespace boost { namespace python { namespace detail {
namespace
{
PyObject* init_module_in_scope(PyObject* m, void(*init_function)())
{
if (m != 0)
{
// Create the current module scope
object m_obj(((borrowed_reference_t*)m));
scope current_module(m_obj);
handle_exception(init_function);
}
return m;
}
}
BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char const* doc)
{
// Use function::add_to_namespace to achieve overloading if
// appropriate.
scope current;
objects::add_to_namespace(current, name, x, doc);
}
#if PY_VERSION_HEX >= 0x03000000
BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef& moduledef, void(*init_function)())
{
return init_module_in_scope(
PyModule_Create(&moduledef),
init_function);
}
#else
namespace
{
PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } };
}
BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*init_function)())
{
return init_module_in_scope(
Py_InitModule(const_cast<char*>(name), initial_methods),
init_function);
}
#endif
}}} // namespace boost::python::detail
namespace boost { namespace python {
namespace detail
{
BOOST_PYTHON_DECL PyObject* current_scope = 0;
}
}}

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "class.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "enum.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "function.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "function_doc_signature.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "inheritance.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "iterator.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "life_support.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "pickle_support.cpp"

View File

@ -0,0 +1,5 @@
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable: 4244 4503 4752 4800 4996)
#define BOOST_PYTHON_SOURCE
#include "stl_iterator.cpp"

View File

@ -0,0 +1,764 @@
// Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/detail/prefix.hpp>
#include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround
#include <boost/python/object/class.hpp>
#include <boost/python/object/instance.hpp>
#include <boost/python/object/class_detail.hpp>
#include <boost/python/scope.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/object/find_instance.hpp>
#include <boost/python/object/pickle_support.hpp>
#include <boost/python/detail/map_entry.hpp>
#include <boost/python/object.hpp>
#include <boost/python/object_protocol.hpp>
#include <boost/detail/binary_search.hpp>
#include <boost/python/self.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/str.hpp>
#include <boost/python/ssize_t.hpp>
#include <functional>
#include <vector>
#include <cstddef>
#include <new>
#include <structmember.h>
namespace boost { namespace python {
# ifdef BOOST_PYTHON_SELF_IS_CLASS
namespace self_ns
{
self_t self;
}
# endif
instance_holder::instance_holder()
: m_next(0)
{
}
instance_holder::~instance_holder()
{
}
extern "C"
{
// This is copied from typeobject.c in the Python sources. Even though
// class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
// filled in by the base class initialization process in
// PyType_Ready(). However, tp_is_gc is *not* copied from the base
// type, making it assume that classes are GC-able even if (like
// class_type_object) they're statically allocated.
static int
type_is_gc(PyTypeObject *python_type)
{
return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
}
// This is also copied from the Python sources. We can't implement
// static_data as a subclass property effectively without it.
typedef struct {
PyObject_HEAD
PyObject *prop_get;
PyObject *prop_set;
PyObject *prop_del;
PyObject *prop_doc;
int getter_doc;
} propertyobject;
// Copied from Python source and removed the part for setting docstring,
// since we don't have a setter for __doc__ and trying to set it will
// cause the init fail.
static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
{
PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
propertyobject *prop = (propertyobject *)self;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
const_cast<char **>(kwlist), &get, &set, &del, &doc))
return -1;
if (get == Py_None)
get = NULL;
if (set == Py_None)
set = NULL;
if (del == Py_None)
del = NULL;
Py_XINCREF(get);
Py_XINCREF(set);
Py_XINCREF(del);
Py_XINCREF(doc);
prop->prop_get = get;
prop->prop_set = set;
prop->prop_del = del;
prop->prop_doc = doc;
prop->getter_doc = 0;
return 0;
}
static PyObject *
static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
{
propertyobject *gs = (propertyobject *)self;
return PyObject_CallFunction(gs->prop_get, const_cast<char*>("()"));
}
static int
static_data_descr_set(PyObject *self, PyObject * /*obj*/, PyObject *value)
{
propertyobject *gs = (propertyobject *)self;
PyObject *func, *res;
if (value == NULL)
func = gs->prop_del;
else
func = gs->prop_set;
if (func == NULL) {
PyErr_SetString(PyExc_AttributeError,
value == NULL ?
"can't delete attribute" :
"can't set attribute");
return -1;
}
if (value == NULL)
res = PyObject_CallFunction(func, const_cast<char*>("()"));
else
res = PyObject_CallFunction(func, const_cast<char*>("(O)"), value);
if (res == NULL)
return -1;
Py_DECREF(res);
return 0;
}
}
static PyTypeObject static_data_object = {
PyVarObject_HEAD_INIT(NULL, 0)
const_cast<char*>("Boost.Python.StaticProperty"),
sizeof(propertyobject),
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, //&PyProperty_Type, /* tp_base */
0, /* tp_dict */
static_data_descr_get, /* tp_descr_get */
static_data_descr_set, /* tp_descr_set */
0, /* tp_dictoffset */
property_init, /* tp_init */
0, /* tp_alloc */
0, // filled in with type_new /* tp_new */
0, // filled in with __PyObject_GC_Del /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
};
namespace objects
{
#if PY_VERSION_HEX < 0x03000000
// XXX Not sure why this run into compiling error in Python 3
extern "C"
{
// This declaration needed due to broken Python 2.2 headers
extern DL_IMPORT(PyTypeObject) PyProperty_Type;
}
#endif
BOOST_PYTHON_DECL PyObject* static_data()
{
if (static_data_object.tp_dict == 0)
{
Py_TYPE(&static_data_object) = &PyType_Type;
static_data_object.tp_base = &PyProperty_Type;
if (PyType_Ready(&static_data_object))
return 0;
}
return upcast<PyObject>(&static_data_object);
}
}
extern "C"
{
// Ordinarily, descriptors have a certain assymetry: you can use
// them to read attributes off the class object they adorn, but
// writing the same attribute on the class object always replaces
// the descriptor in the class __dict__. In order to properly
// represent C++ static data members, we need to allow them to be
// written through the class instance. This function of the
// metaclass makes it possible.
static int
class_setattro(PyObject *obj, PyObject *name, PyObject* value)
{
// Must use "private" Python implementation detail
// _PyType_Lookup instead of PyObject_GetAttr because the
// latter will always end up calling the descr_get function on
// any descriptor it finds; we need the unadulterated
// descriptor here.
PyObject* a = _PyType_Lookup(downcast<PyTypeObject>(obj), name);
// a is a borrowed reference or 0
// If we found a static data descriptor, call it directly to
// force it to set the static data member
if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
return Py_TYPE(a)->tp_descr_set(a, obj, value);
else
return PyType_Type.tp_setattro(obj, name, value);
}
}
static PyTypeObject class_metatype_object = {
PyVarObject_HEAD_INIT(NULL, 0)
const_cast<char*>("Boost.Python.class"),
PyType_Type.tp_basicsize,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
class_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, //&PyType_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, // filled in with type_new /* tp_new */
0, // filled in with __PyObject_GC_Del /* tp_free */
(inquiry)type_is_gc, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
};
// Install the instance data for a C++ object into a Python instance
// object.
void instance_holder::install(PyObject* self) throw()
{
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self)), &class_metatype_object));
m_next = ((objects::instance<>*)self)->objects;
((objects::instance<>*)self)->objects = this;
}
namespace objects
{
// Get the metatype object for all extension classes.
BOOST_PYTHON_DECL type_handle class_metatype()
{
if (class_metatype_object.tp_dict == 0)
{
Py_TYPE(&class_metatype_object) = &PyType_Type;
class_metatype_object.tp_base = &PyType_Type;
if (PyType_Ready(&class_metatype_object))
return type_handle();
}
return type_handle(borrowed(&class_metatype_object));
}
extern "C"
{
static void instance_dealloc(PyObject* inst)
{
instance<>* kill_me = (instance<>*)inst;
for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
{
next = p->next();
p->~instance_holder();
instance_holder::deallocate(inst, dynamic_cast<void*>(p));
}
// Python 2.2.1 won't add weak references automatically when
// tp_itemsize > 0, so we need to manage that
// ourselves. Accordingly, we also have to clean up the
// weakrefs ourselves.
if (kill_me->weakrefs != NULL)
PyObject_ClearWeakRefs(inst);
Py_XDECREF(kill_me->dict);
Py_TYPE(inst)->tp_free(inst);
}
static PyObject *
instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/)
{
// Attempt to find the __instance_size__ attribute. If not present, no problem.
PyObject* d = type_->tp_dict;
PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));
ssize_t instance_size = instance_size_obj ?
#if PY_VERSION_HEX >= 0x03000000
PyLong_AsSsize_t(instance_size_obj) : 0;
#else
PyInt_AsLong(instance_size_obj) : 0;
#endif
if (instance_size < 0)
instance_size = 0;
PyErr_Clear(); // Clear any errors that may have occurred.
instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size);
if (result)
{
// Guido says we can use ob_size for any purpose we
// like, so we'll store the total size of the object
// there. A negative number indicates that the extra
// instance memory is not yet allocated to any holders.
#if PY_VERSION_HEX >= 0x02060000
Py_SIZE(result) =
#else
result->ob_size =
#endif
-(static_cast<int>(offsetof(instance<>,storage) + instance_size));
}
return (PyObject*)result;
}
static PyObject* instance_get_dict(PyObject* op, void*)
{
instance<>* inst = downcast<instance<> >(op);
if (inst->dict == 0)
inst->dict = PyDict_New();
return python::xincref(inst->dict);
}
static int instance_set_dict(PyObject* op, PyObject* dict, void*)
{
instance<>* inst = downcast<instance<> >(op);
python::xdecref(inst->dict);
inst->dict = python::incref(dict);
return 0;
}
}
static PyGetSetDef instance_getsets[] = {
{const_cast<char*>("__dict__"), instance_get_dict, instance_set_dict, NULL, 0},
{0, 0, 0, 0, 0}
};
static PyMemberDef instance_members[] = {
{const_cast<char*>("__weakref__"), T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},
{0, 0, 0, 0, 0}
};
static PyTypeObject class_type_object = {
PyVarObject_HEAD_INIT(NULL, 0)
const_cast<char*>("Boost.Python.instance"),
offsetof(instance<>,storage), /* tp_basicsize */
1, /* tp_itemsize */
instance_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(instance<>,weakrefs), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
instance_members, /* tp_members */
instance_getsets, /* tp_getset */
0, //&PyBaseObject_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(instance<>,dict), /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
instance_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
};
BOOST_PYTHON_DECL type_handle class_type()
{
if (class_type_object.tp_dict == 0)
{
Py_TYPE(&class_type_object) = incref(class_metatype().get());
class_type_object.tp_base = &PyBaseObject_Type;
if (PyType_Ready(&class_type_object))
return type_handle();
// class_type_object.tp_setattro = class_setattro;
}
return type_handle(borrowed(&class_type_object));
}
BOOST_PYTHON_DECL void*
find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
{
if (!Py_TYPE(Py_TYPE(inst)) ||
!PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), &class_metatype_object))
return 0;
instance<>* self = reinterpret_cast<instance<>*>(inst);
for (instance_holder* match = self->objects; match != 0; match = match->next())
{
void* const found = match->holds(type, null_shared_ptr_only);
if (found)
return found;
}
return 0;
}
object module_prefix()
{
return object(
PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
? object(scope().attr("__name__"))
: api::getattr(scope(), "__module__", str())
);
}
namespace
{
// Find a registered class object corresponding to id. Return a
// null handle if no such class is registered.
inline type_handle query_class(type_info id)
{
converter::registration const* p = converter::registry::query(id);
return type_handle(
python::borrowed(
python::allow_null(p ? p->m_class_object : 0))
);
}
// Find a registered class corresponding to id. If not found,
// throw an appropriate exception.
type_handle get_class(type_info id)
{
type_handle result(query_class(id));
if (result.get() == 0)
{
object report("extension class wrapper for base class ");
report = report + id.name() + " has not been created yet";
PyErr_SetObject(PyExc_RuntimeError, report.ptr());
throw_error_already_set();
}
return result;
}
// class_base constructor
//
// name - the name of the new Python class
//
// num_types - one more than the number of declared bases
//
// types - array of python::type_info, the first item
// corresponding to the class being created, and the
// rest corresponding to its declared bases.
//
inline object
new_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc)
{
assert(num_types >= 1);
// Build a tuple of the base Python type objects. If no bases
// were declared, we'll use our class_type() as the single base
// class.
ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
handle<> bases(PyTuple_New(num_bases));
for (ssize_t i = 1; i <= num_bases; ++i)
{
type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
// PyTuple_SET_ITEM steals this reference
PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
}
// Call the class metatype to create a new class
dict d;
object m = module_prefix();
if (m) d["__module__"] = m;
if (doc != 0)
d["__doc__"] = doc;
object result = object(class_metatype())(name, bases, d);
assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
if (scope().ptr() != Py_None)
scope().attr(name) = result;
// For pickle. Will lead to informative error messages if pickling
// is not enabled.
result.attr("__reduce__") = object(make_instance_reduce_function());
return result;
}
}
class_base::class_base(
char const* name, std::size_t num_types, type_info const* const types, char const* doc)
: object(new_class(name, num_types, types, doc))
{
// Insert the new class object in the registry
converter::registration& converters = const_cast<converter::registration&>(
converter::registry::lookup(types[0]));
// Class object is leaked, for now
converters.m_class_object = (PyTypeObject*)incref(this->ptr());
}
BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst)
{
converter::registration& dst_converters
= const_cast<converter::registration&>(converter::registry::lookup(dst));
converter::registration const& src_converters = converter::registry::lookup(src);
dst_converters.m_class_object = src_converters.m_class_object;
}
void class_base::set_instance_size(std::size_t instance_size)
{
this->attr("__instance_size__") = instance_size;
}
void class_base::add_property(
char const* name, object const& fget, char const* docstr)
{
object property(
(python::detail::new_reference)
PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), 0, 0, docstr));
this->setattr(name, property);
}
void class_base::add_property(
char const* name, object const& fget, object const& fset, char const* docstr)
{
object property(
(python::detail::new_reference)
PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), 0, docstr));
this->setattr(name, property);
}
void class_base::add_static_property(char const* name, object const& fget)
{
object property(
(python::detail::new_reference)
PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr())
);
this->setattr(name, property);
}
void class_base::add_static_property(char const* name, object const& fget, object const& fset)
{
object property(
(python::detail::new_reference)
PyObject_CallFunction(static_data(), const_cast<char*>("OO"), fget.ptr(), fset.ptr()));
this->setattr(name, property);
}
void class_base::setattr(char const* name, object const& x)
{
if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
throw_error_already_set();
}
namespace
{
extern "C" PyObject* no_init(PyObject*, PyObject*)
{
::PyErr_SetString(::PyExc_RuntimeError, const_cast<char*>("This class cannot be instantiated from Python"));
return NULL;
}
static ::PyMethodDef no_init_def = {
const_cast<char*>("__init__"), no_init, METH_VARARGS,
const_cast<char*>("Raises an exception\n"
"This class cannot be instantiated from Python\n")
};
}
void class_base::def_no_init()
{
handle<> f(::PyCFunction_New(&no_init_def, 0));
this->setattr("__init__", object(f));
}
void class_base::enable_pickling_(bool getstate_manages_dict)
{
setattr("__safe_for_unpickling__", object(true));
if (getstate_manages_dict)
{
setattr("__getstate_manages_dict__", object(true));
}
}
namespace
{
PyObject* callable_check(PyObject* callable)
{
if (PyCallable_Check(expect_non_null(callable)))
return callable;
::PyErr_Format(
PyExc_TypeError
, const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
, Py_TYPE(callable)->tp_name
);
throw_error_already_set();
return 0;
}
}
void class_base::make_method_static(const char * method_name)
{
PyTypeObject* self = downcast<PyTypeObject>(this->ptr());
dict d((handle<>(borrowed(self->tp_dict))));
object method(d[method_name]);
this->attr(method_name) = object(
handle<>(
PyStaticMethod_New((callable_check)(method.ptr()) )
));
}
BOOST_PYTHON_DECL type_handle registered_class_object(type_info id)
{
return query_class(id);
}
} // namespace objects
void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
{
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
objects::instance<>* self = (objects::instance<>*)self_;
int total_size_needed = holder_offset + holder_size;
if (-Py_SIZE(self) >= total_size_needed)
{
// holder_offset should at least point into the variable-sized part
assert(holder_offset >= offsetof(objects::instance<>,storage));
// Record the fact that the storage is occupied, noting where it starts
Py_SIZE(self) = holder_offset;
return (char*)self + holder_offset;
}
else
{
void* const result = PyMem_Malloc(holder_size);
if (result == 0)
throw std::bad_alloc();
return result;
}
}
void instance_holder::deallocate(PyObject* self_, void* storage) throw()
{
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
objects::instance<>* self = (objects::instance<>*)self_;
if (storage != (char*)self + Py_SIZE(self))
{
PyMem_Free(storage);
}
}
}} // namespace boost::python

View File

@ -0,0 +1,252 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object/enum_base.hpp>
#include <boost/python/cast.hpp>
#include <boost/python/scope.hpp>
#include <boost/python/object.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/str.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/object_protocol.hpp>
#include <structmember.h>
namespace boost { namespace python { namespace objects {
struct enum_object
{
#if PY_VERSION_HEX >= 0x03000000
PyLongObject base_object;
#else
PyIntObject base_object;
#endif
PyObject* name;
};
static PyMemberDef enum_members[] = {
{const_cast<char*>("name"), T_OBJECT_EX, offsetof(enum_object,name),READONLY, 0},
{0, 0, 0, 0, 0}
};
extern "C"
{
static void
enum_dealloc(enum_object* self)
{
Py_XDECREF(self->name);
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject* enum_repr(PyObject* self_)
{
PyObject *mod = PyObject_GetAttrString( self_, "__module__");
object auto_free = object(handle<>(mod));
enum_object* self = downcast<enum_object>(self_);
if (!self->name)
{
return
#if PY_VERSION_HEX >= 0x03000000
PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_));
#else
PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_));
#endif
}
else
{
PyObject* name = self->name;
if (name == 0)
return 0;
return
#if PY_VERSION_HEX >= 0x03000000
PyUnicode_FromFormat("%S.%s.%S", mod, self_->ob_type->tp_name, name);
#else
PyString_FromFormat("%s.%s.%s",
PyString_AsString(mod), self_->ob_type->tp_name, PyString_AsString(name));
#endif
}
}
static PyObject* enum_str(PyObject* self_)
{
enum_object* self = downcast<enum_object>(self_);
if (!self->name)
{
#if PY_VERSION_HEX >= 0x03000000
return PyLong_Type.tp_str(self_);
#else
return PyInt_Type.tp_str(self_);
#endif
}
else
{
return incref(self->name);
}
}
}
static PyTypeObject enum_type_object = {
PyVarObject_HEAD_INIT(NULL, 0) // &PyType_Type
const_cast<char*>("Boost.Python.enum"),
sizeof(enum_object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) enum_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
enum_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
enum_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT
#if PY_VERSION_HEX < 0x03000000
| Py_TPFLAGS_CHECKTYPES
#endif
| Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
enum_members, /* tp_members */
0, /* tp_getset */
0, //&PyInt_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
};
object module_prefix();
namespace
{
object new_enum_type(char const* name, char const *doc)
{
if (enum_type_object.tp_dict == 0)
{
Py_TYPE(&enum_type_object) = incref(&PyType_Type);
#if PY_VERSION_HEX >= 0x03000000
enum_type_object.tp_base = &PyLong_Type;
#else
enum_type_object.tp_base = &PyInt_Type;
#endif
if (PyType_Ready(&enum_type_object))
throw_error_already_set();
}
type_handle metatype(borrowed(&PyType_Type));
type_handle base(borrowed(&enum_type_object));
// suppress the instance __dict__ in these enum objects. There
// may be a slicker way, but this'll do for now.
dict d;
d["__slots__"] = tuple();
d["values"] = dict();
d["names"] = dict();
object module_name = module_prefix();
if (module_name)
d["__module__"] = module_name;
if (doc)
d["__doc__"] = doc;
object result = (object(metatype))(name, make_tuple(base), d);
scope().attr(name) = result;
return result;
}
}
enum_base::enum_base(
char const* name
, converter::to_python_function_t to_python
, converter::convertible_function convertible
, converter::constructor_function construct
, type_info id
, char const *doc
)
: object(new_enum_type(name, doc))
{
converter::registration& converters
= const_cast<converter::registration&>(
converter::registry::lookup(id));
converters.m_class_object = downcast<PyTypeObject>(this->ptr());
converter::registry::insert(to_python, id);
converter::registry::insert(convertible, construct, id);
}
void enum_base::add_value(char const* name_, long value)
{
// Convert name to Python string
object name(name_);
// Create a new enum instance by calling the class with a value
object x = (*this)(value);
// Store the object in the enum class
(*this).attr(name_) = x;
dict d = extract<dict>(this->attr("values"))();
d[value] = x;
// Set the name field in the new enum instanec
enum_object* p = downcast<enum_object>(x.ptr());
Py_XDECREF(p->name);
p->name = incref(name.ptr());
dict names_dict = extract<dict>(this->attr("names"))();
names_dict[x.attr("name")] = x;
}
void enum_base::export_values()
{
dict d = extract<dict>(this->attr("names"))();
list items = d.items();
scope current;
for (unsigned i = 0, max = len(items); i < max; ++i)
api::setattr(current, items[i][0], items[i][1]);
}
PyObject* enum_base::to_python(PyTypeObject* type_, long x)
{
object type((type_handle(borrowed(type_))));
dict d = extract<dict>(type.attr("values"))();
object v = d.get(x, object());
return incref(
(v == object() ? type(x) : v).ptr());
}
}}} // namespace boost::python::object

View File

@ -0,0 +1,793 @@
// Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/docstring_options.hpp>
#include <boost/python/object/function_object.hpp>
#include <boost/python/object/function_handle.hpp>
#include <boost/python/object/function_doc_signature.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/str.hpp>
#include <boost/python/object_attributes.hpp>
#include <boost/python/args.hpp>
#include <boost/python/refcount.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/list.hpp>
#include <boost/python/ssize_t.hpp>
#include <boost/python/detail/signature.hpp>
#include <boost/python/detail/none.hpp>
#include <boost/mpl/vector/vector10.hpp>
#include <boost/bind.hpp>
#include <algorithm>
#include <cstring>
#if BOOST_PYTHON_DEBUG_ERROR_MESSAGES
# include <cstdio>
#endif
namespace boost { namespace python {
volatile bool docstring_options::show_user_defined_ = true;
volatile bool docstring_options::show_cpp_signatures_ = true;
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
volatile bool docstring_options::show_py_signatures_ = true;
#else
volatile bool docstring_options::show_py_signatures_ = false;
#endif
}}
namespace boost { namespace python { namespace objects {
py_function_impl_base::~py_function_impl_base()
{
}
unsigned py_function_impl_base::max_arity() const
{
return this->min_arity();
}
extern PyTypeObject function_type;
function::function(
py_function const& implementation
#if BOOST_WORKAROUND(__EDG_VERSION__, == 245)
, python::detail::keyword const* names_and_defaults
#else
, python::detail::keyword const* const names_and_defaults
#endif
, unsigned num_keywords
)
: m_fn(implementation)
, m_nkeyword_values(0)
{
if (names_and_defaults != 0)
{
unsigned int max_arity = m_fn.max_arity();
unsigned int keyword_offset
= max_arity > num_keywords ? max_arity - num_keywords : 0;
ssize_t tuple_size = num_keywords ? max_arity : 0;
m_arg_names = object(handle<>(PyTuple_New(tuple_size)));
if (num_keywords != 0)
{
for (unsigned j = 0; j < keyword_offset; ++j)
PyTuple_SET_ITEM(m_arg_names.ptr(), j, incref(Py_None));
}
for (unsigned i = 0; i < num_keywords; ++i)
{
tuple kv;
python::detail::keyword const* const p = names_and_defaults + i;
if (p->default_value)
{
kv = make_tuple(p->name, p->default_value);
++m_nkeyword_values;
}
else
{
kv = make_tuple(p->name);
}
PyTuple_SET_ITEM(
m_arg_names.ptr()
, i + keyword_offset
, incref(kv.ptr())
);
}
}
PyObject* p = this;
if (Py_TYPE(&function_type) == 0)
{
Py_TYPE(&function_type) = &PyType_Type;
::PyType_Ready(&function_type);
}
(void)( // warning suppression for GCC
PyObject_INIT(p, &function_type)
);
}
function::~function()
{
}
PyObject* function::call(PyObject* args, PyObject* keywords) const
{
std::size_t n_unnamed_actual = PyTuple_GET_SIZE(args);
std::size_t n_keyword_actual = keywords ? PyDict_Size(keywords) : 0;
std::size_t n_actual = n_unnamed_actual + n_keyword_actual;
function const* f = this;
// Try overloads looking for a match
do
{
// Check for a plausible number of arguments
unsigned min_arity = f->m_fn.min_arity();
unsigned max_arity = f->m_fn.max_arity();
if (n_actual + f->m_nkeyword_values >= min_arity
&& n_actual <= max_arity)
{
// This will be the args that actually get passed
handle<>inner_args(allow_null(borrowed(args)));
if (n_keyword_actual > 0 // Keyword arguments were supplied
|| n_actual < min_arity) // or default keyword values are needed
{
if (f->m_arg_names.is_none())
{
// this overload doesn't accept keywords
inner_args = handle<>();
}
else
{
// "all keywords are none" is a special case
// indicating we will accept any number of keyword
// arguments
if (PyTuple_Size(f->m_arg_names.ptr()) == 0)
{
// no argument preprocessing
}
else if (n_actual > max_arity)
{
// too many arguments
inner_args = handle<>();
}
else
{
// build a new arg tuple, will adjust its size later
assert(max_arity <= static_cast<std::size_t>(ssize_t_max));
inner_args = handle<>(
PyTuple_New(static_cast<ssize_t>(max_arity)));
// Fill in the positional arguments
for (std::size_t i = 0; i < n_unnamed_actual; ++i)
PyTuple_SET_ITEM(inner_args.get(), i, incref(PyTuple_GET_ITEM(args, i)));
// Grab remaining arguments by name from the keyword dictionary
std::size_t n_actual_processed = n_unnamed_actual;
for (std::size_t arg_pos = n_unnamed_actual; arg_pos < max_arity ; ++arg_pos)
{
// Get the keyword[, value pair] corresponding
PyObject* kv = PyTuple_GET_ITEM(f->m_arg_names.ptr(), arg_pos);
// If there were any keyword arguments,
// look up the one we need for this
// argument position
PyObject* value = n_keyword_actual
? PyDict_GetItem(keywords, PyTuple_GET_ITEM(kv, 0))
: 0;
if (!value)
{
// Not found; check if there's a default value
if (PyTuple_GET_SIZE(kv) > 1)
value = PyTuple_GET_ITEM(kv, 1);
if (!value)
{
// still not found; matching fails
PyErr_Clear();
inner_args = handle<>();
break;
}
}
else
{
++n_actual_processed;
}
PyTuple_SET_ITEM(inner_args.get(), arg_pos, incref(value));
}
if (inner_args.get())
{
//check if we proccessed all the arguments
if(n_actual_processed < n_actual)
inner_args = handle<>();
}
}
}
}
// Call the function. Pass keywords in case it's a
// function accepting any number of keywords
PyObject* result = inner_args ? f->m_fn(inner_args.get(), keywords) : 0;
// If the result is NULL but no error was set, m_fn failed
// the argument-matching test.
// This assumes that all other error-reporters are
// well-behaved and never return NULL to python without
// setting an error.
if (result != 0 || PyErr_Occurred())
return result;
}
f = f->m_overloads.get();
}
while (f);
// None of the overloads matched; time to generate the error message
argument_error(args, keywords);
return 0;
}
object function::signature(bool show_return_type) const
{
py_function const& impl = m_fn;
python::detail::signature_element const* return_type = impl.signature();
python::detail::signature_element const* s = return_type + 1;
list formal_params;
if (impl.max_arity() == 0)
formal_params.append("void");
for (unsigned n = 0; n < impl.max_arity(); ++n)
{
if (s[n].basename == 0)
{
formal_params.append("...");
break;
}
str param(s[n].basename);
if (s[n].lvalue)
param += " {lvalue}";
if (m_arg_names) // None or empty tuple will test false
{
object kv(m_arg_names[n]);
if (kv)
{
char const* const fmt = len(kv) > 1 ? " %s=%r" : " %s";
param += fmt % kv;
}
}
formal_params.append(param);
}
if (show_return_type)
return "%s(%s) -> %s" % make_tuple(
m_name, str(", ").join(formal_params), return_type->basename);
return "%s(%s)" % make_tuple(
m_name, str(", ").join(formal_params));
}
object function::signatures(bool show_return_type) const
{
list result;
for (function const* f = this; f; f = f->m_overloads.get()) {
result.append(f->signature(show_return_type));
}
return result;
}
void function::argument_error(PyObject* args, PyObject* /*keywords*/) const
{
static handle<> exception(
PyErr_NewException(const_cast<char*>("Boost.Python.ArgumentError"), PyExc_TypeError, 0));
object message = "Python argument types in\n %s.%s("
% make_tuple(this->m_namespace, this->m_name);
list actual_args;
for (ssize_t i = 0; i < PyTuple_Size(args); ++i)
{
char const* name = PyTuple_GetItem(args, i)->ob_type->tp_name;
actual_args.append(str(name));
}
message += str(", ").join(actual_args);
message += ")\ndid not match C++ signature:\n ";
message += str("\n ").join(signatures());
#if BOOST_PYTHON_DEBUG_ERROR_MESSAGES
std::printf("\n--------\n%s\n--------\n", extract<const char*>(message)());
#endif
PyErr_SetObject(exception.get(), message.ptr());
throw_error_already_set();
}
void function::add_overload(handle<function> const& overload_)
{
function* parent = this;
while (parent->m_overloads)
parent = parent->m_overloads.get();
parent->m_overloads = overload_;
// If we have no documentation, get the docs from the overload
if (!m_doc)
m_doc = overload_->m_doc;
}
namespace
{
char const* const binary_operator_names[] =
{
"add__",
"and__",
"div__",
"divmod__",
"eq__",
"floordiv__",
"ge__",
"gt__",
"le__",
"lshift__",
"lt__",
"mod__",
"mul__",
"ne__",
"or__",
"pow__",
"radd__",
"rand__",
"rdiv__",
"rdivmod__",
"rfloordiv__",
"rlshift__",
"rmod__",
"rmul__",
"ror__",
"rpow__",
"rrshift__",
"rshift__",
"rsub__",
"rtruediv__",
"rxor__",
"sub__",
"truediv__",
"xor__"
};
struct less_cstring
{
bool operator()(char const* x, char const* y) const
{
return BOOST_CSTD_::strcmp(x,y) < 0;
}
};
inline bool is_binary_operator(char const* name)
{
return name[0] == '_'
&& name[1] == '_'
&& std::binary_search(
&binary_operator_names[0]
, binary_operator_names + sizeof(binary_operator_names)/sizeof(*binary_operator_names)
, name + 2
, less_cstring()
);
}
// Something for the end of the chain of binary operators
PyObject* not_implemented(PyObject*, PyObject*)
{
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
handle<function> not_implemented_function()
{
static object keeper(
function_object(
py_function(&not_implemented, mpl::vector1<void>(), 2)
, python::detail::keyword_range())
);
return handle<function>(borrowed(downcast<function>(keeper.ptr())));
}
}
void function::add_to_namespace(
object const& name_space, char const* name_, object const& attribute)
{
add_to_namespace(name_space, name_, attribute, 0);
}
namespace detail
{
extern char py_signature_tag[];
extern char cpp_signature_tag[];
}
void function::add_to_namespace(
object const& name_space, char const* name_, object const& attribute, char const* doc)
{
str const name(name_);
PyObject* const ns = name_space.ptr();
if (attribute.ptr()->ob_type == &function_type)
{
function* new_func = downcast<function>(attribute.ptr());
handle<> dict;
#if PY_VERSION_HEX < 0x03000000
// Old-style class gone in Python 3
if (PyClass_Check(ns))
dict = handle<>(borrowed(((PyClassObject*)ns)->cl_dict));
else
#endif
if (PyType_Check(ns))
dict = handle<>(borrowed(((PyTypeObject*)ns)->tp_dict));
else
dict = handle<>(PyObject_GetAttrString(ns, const_cast<char*>("__dict__")));
if (dict == 0)
throw_error_already_set();
handle<> existing(allow_null(::PyObject_GetItem(dict.get(), name.ptr())));
if (existing)
{
if (existing->ob_type == &function_type)
{
new_func->add_overload(
handle<function>(
borrowed(
downcast<function>(existing.get())
)
)
);
}
else if (existing->ob_type == &PyStaticMethod_Type)
{
char const* name_space_name = extract<char const*>(name_space.attr("__name__"));
::PyErr_Format(
PyExc_RuntimeError
, "Boost.Python - All overloads must be exported "
"before calling \'class_<...>(\"%s\").staticmethod(\"%s\")\'"
, name_space_name
, name_
);
throw_error_already_set();
}
}
else if (is_binary_operator(name_))
{
// Binary operators need an additional overload which
// returns NotImplemented, so that Python will try the
// __rxxx__ functions on the other operand. We add this
// when no overloads for the operator already exist.
new_func->add_overload(not_implemented_function());
}
// A function is named the first time it is added to a namespace.
if (new_func->name().is_none())
new_func->m_name = name;
handle<> name_space_name(
allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast<char*>("__name__"))));
if (name_space_name)
new_func->m_namespace = object(name_space_name);
}
// The PyObject_GetAttrString() or PyObject_GetItem calls above may
// have left an active error
PyErr_Clear();
if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0)
throw_error_already_set();
object mutable_attribute(attribute);
/*
if (doc != 0 && docstring_options::show_user_defined_)
{
// Accumulate documentation
if (
PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
&& mutable_attribute.attr("__doc__"))
{
mutable_attribute.attr("__doc__") += "\n\n";
mutable_attribute.attr("__doc__") += doc;
}
else {
mutable_attribute.attr("__doc__") = doc;
}
}
if (docstring_options::show_signatures_)
{
if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
&& mutable_attribute.attr("__doc__")) {
mutable_attribute.attr("__doc__") += (
mutable_attribute.attr("__doc__")[-1] != "\n" ? "\n\n" : "\n");
}
else {
mutable_attribute.attr("__doc__") = "";
}
function* f = downcast<function>(attribute.ptr());
mutable_attribute.attr("__doc__") += str("\n ").join(make_tuple(
"C++ signature:", f->signature(true)));
}
*/
str _doc;
if (docstring_options::show_py_signatures_)
{
_doc += str(const_cast<const char*>(detail::py_signature_tag));
}
if (doc != 0 && docstring_options::show_user_defined_)
_doc += doc;
if (docstring_options::show_cpp_signatures_)
{
_doc += str(const_cast<const char*>(detail::cpp_signature_tag));
}
if(_doc)
{
object mutable_attribute(attribute);
mutable_attribute.attr("__doc__")= _doc;
}
}
BOOST_PYTHON_DECL void add_to_namespace(
object const& name_space, char const* name, object const& attribute)
{
function::add_to_namespace(name_space, name, attribute, 0);
}
BOOST_PYTHON_DECL void add_to_namespace(
object const& name_space, char const* name, object const& attribute, char const* doc)
{
function::add_to_namespace(name_space, name, attribute, doc);
}
namespace
{
struct bind_return
{
bind_return(PyObject*& result, function const* f, PyObject* args, PyObject* keywords)
: m_result(result)
, m_f(f)
, m_args(args)
, m_keywords(keywords)
{}
void operator()() const
{
m_result = m_f->call(m_args, m_keywords);
}
private:
PyObject*& m_result;
function const* m_f;
PyObject* m_args;
PyObject* m_keywords;
};
}
extern "C"
{
// Stolen from Python's funcobject.c
static PyObject *
function_descr_get(PyObject *func, PyObject *obj, PyObject *type_)
{
#if PY_VERSION_HEX >= 0x03000000
// The implement is different in Python 3 because of the removal of unbound method
if (obj == Py_None || obj == NULL) {
Py_INCREF(func);
return func;
}
return PyMethod_New(func, obj);
#else
if (obj == Py_None)
obj = NULL;
return PyMethod_New(func, obj, type_);
#endif
}
static void
function_dealloc(PyObject* p)
{
delete static_cast<function*>(p);
}
static PyObject *
function_call(PyObject *func, PyObject *args, PyObject *kw)
{
PyObject* result = 0;
handle_exception(bind_return(result, static_cast<function*>(func), args, kw));
return result;
}
//
// Here we're using the function's tp_getset rather than its
// tp_members to set up __doc__ and __name__, because tp_members
// really depends on having a POD object type (it relies on
// offsets). It might make sense to reformulate function as a POD
// at some point, but this is much more expedient.
//
static PyObject* function_get_doc(PyObject* op, void*)
{
function* f = downcast<function>(op);
list signatures = function_doc_signature_generator::function_doc_signatures(f);
if(!signatures) return python::detail::none();
signatures.reverse();
return python::incref( str("\n").join(signatures).ptr());
}
static int function_set_doc(PyObject* op, PyObject* doc, void*)
{
function* f = downcast<function>(op);
f->doc(doc ? object(python::detail::borrowed_reference(doc)) : object());
return 0;
}
static PyObject* function_get_name(PyObject* op, void*)
{
function* f = downcast<function>(op);
if (f->name().is_none())
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_InternFromString("<unnamed Boost.Python function>");
#else
return PyString_InternFromString("<unnamed Boost.Python function>");
#endif
else
return python::incref(f->name().ptr());
}
// We add a dummy __class__ attribute in order to fool PyDoc into
// treating these as built-in functions and scanning their
// documentation
static PyObject* function_get_class(PyObject* /*op*/, void*)
{
return python::incref(upcast<PyObject>(&PyCFunction_Type));
}
static PyObject* function_get_module(PyObject* op, void*)
{
function* f = downcast<function>(op);
object const& ns = f->get_namespace();
if (!ns.is_none()) {
return python::incref(ns.ptr());
}
PyErr_SetString(
PyExc_AttributeError, const_cast<char*>(
"Boost.Python function __module__ unknown."));
return 0;
}
}
static PyGetSetDef function_getsetlist[] = {
{const_cast<char*>("__name__"), (getter)function_get_name, 0, 0, 0 },
{const_cast<char*>("func_name"), (getter)function_get_name, 0, 0, 0 },
{const_cast<char*>("__module__"), (getter)function_get_module, 0, 0, 0 },
{const_cast<char*>("func_module"), (getter)function_get_module, 0, 0, 0 },
{const_cast<char*>("__class__"), (getter)function_get_class, 0, 0, 0 }, // see note above
{const_cast<char*>("__doc__"), (getter)function_get_doc, (setter)function_set_doc, 0, 0},
{const_cast<char*>("func_doc"), (getter)function_get_doc, (setter)function_set_doc, 0, 0},
{NULL, 0, 0, 0, 0} /* Sentinel */
};
PyTypeObject function_type = {
PyVarObject_HEAD_INIT(NULL, 0)
const_cast<char*>("Boost.Python.function"),
sizeof(function),
0,
(destructor)function_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, //(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
function_call, /* tp_call */
0, /* tp_str */
0, // PyObject_GenericGetAttr, /* tp_getattro */
0, // PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
0, /* tp_doc */
0, // (traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, // func_memberlist, /* tp_members */
function_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
function_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
};
object function_object(
py_function const& f
, python::detail::keyword_range const& keywords)
{
return python::object(
python::detail::new_non_null_reference(
new function(
f, keywords.first, keywords.second - keywords.first)));
}
object function_object(py_function const& f)
{
return function_object(f, python::detail::keyword_range());
}
handle<> function_handle_impl(py_function const& f)
{
return python::handle<>(
allow_null(
new function(f, 0, 0)));
}
} // namespace objects
namespace detail
{
object BOOST_PYTHON_DECL make_raw_function(objects::py_function f)
{
static keyword k;
return objects::function_object(
f
, keyword_range(&k,&k));
}
void BOOST_PYTHON_DECL pure_virtual_called()
{
PyErr_SetString(
PyExc_RuntimeError, const_cast<char*>("Pure virtual function called"));
throw_error_already_set();
}
}
}} // namespace boost::python

View File

@ -0,0 +1,344 @@
// Copyright Nikolay Mladenov 2007.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// boost::python::make_tuple below are for gcc 4.4 -std=c++0x compatibility
// (Intel C++ 10 and 11 with -std=c++0x don't need the full qualification).
#include <boost/python/converter/registrations.hpp>
#include <boost/python/object/function_doc_signature.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/str.hpp>
#include <boost/python/args.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/detail/signature.hpp>
#include <vector>
namespace boost { namespace python { namespace objects {
bool function_doc_signature_generator::arity_cmp( function const *f1, function const *f2 )
{
return f1->m_fn.max_arity() < f2->m_fn.max_arity();
}
bool function_doc_signature_generator::are_seq_overloads( function const *f1, function const *f2 , bool check_docs)
{
py_function const & impl1 = f1->m_fn;
py_function const & impl2 = f2->m_fn;
//the number of parameters differs by 1
if (impl2.max_arity()-impl1.max_arity() != 1)
return false;
// if check docs then f1 shold not have docstring or have the same docstring as f2
if (check_docs && f2->doc() != f1->doc() && f1->doc())
return false;
python::detail::signature_element const* s1 = impl1.signature();
python::detail::signature_element const* s2 = impl2.signature();
unsigned size = impl1.max_arity()+1;
for (unsigned i = 0; i != size; ++i)
{
//check if the argument types are the same
if (s1[i].basename != s2[i].basename)
return false;
//return type
if (!i) continue;
//check if the argument default values are the same
bool f1_has_names = bool(f1->m_arg_names);
bool f2_has_names = bool(f2->m_arg_names);
if ( (f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1])
|| (f1_has_names && !f2_has_names)
|| (!f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object())
)
return false;
}
return true;
}
std::vector<function const*> function_doc_signature_generator::flatten(function const *f)
{
object name = f->name();
std::vector<function const*> res;
while (f) {
//this if takes out the not_implemented_function
if (f->name() == name)
res.push_back(f);
f=f->m_overloads.get();
}
//std::sort(res.begin(),res.end(), &arity_cmp);
return res;
}
std::vector<function const*> function_doc_signature_generator::split_seq_overloads( const std::vector<function const *> &funcs, bool split_on_doc_change)
{
std::vector<function const*> res;
std::vector<function const*>::const_iterator fi = funcs.begin();
function const * last = *fi;
while (++fi != funcs.end()){
//check if fi starts a new chain of overloads
if (!are_seq_overloads( last, *fi, split_on_doc_change ))
res.push_back(last);
last = *fi;
}
if (last)
res.push_back(last);
return res;
}
str function_doc_signature_generator::raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types )
{
str res("object");
res = str("%s %s(%s)" % make_tuple( res, f->m_name, str("tuple args, dict kwds")) );
return res;
}
const char * function_doc_signature_generator::py_type_str(const python::detail::signature_element &s)
{
if (s.basename==std::string("void")){
static const char * none = "None";
return none;
}
PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0;
if ( py_type )
return py_type->tp_name;
else{
static const char * object = "object";
return object;
}
}
str function_doc_signature_generator::parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types)
{
str param;
python::detail::signature_element const * s = f.signature();
if (cpp_types)
{
if(!n)
s = &f.get_return_type();
if (s[n].basename == 0)
{
return str("...");
}
param = str(s[n].basename);
if (s[n].lvalue)
param += " {lvalue}";
}
else
{
if (n) //we are processing an argument and trying to come up with a name for it
{
object kv;
if ( arg_names && (kv = arg_names[n-1]) )
param = str( " (%s)%s" % make_tuple(py_type_str(s[n]),kv[0]) );
else
param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n]),"arg", n) );
}
else //we are processing the return type
param = py_type_str(f.get_return_type());
}
//an argument - check for default value and append it
if(n && arg_names)
{
object kv(arg_names[n-1]);
if (kv && len(kv) == 2)
{
param = str("%s=%r" % make_tuple(param, kv[1]));
}
}
return param;
}
str function_doc_signature_generator::pretty_signature(function const *f, size_t n_overloads, bool cpp_types )
{
py_function
const& impl = f->m_fn;
;
unsigned arity = impl.max_arity();
if(arity == unsigned(-1))// is this the proper raw function test?
{
return raw_function_pretty_signature(f,n_overloads,cpp_types);
}
list formal_params;
size_t n_extra_default_args=0;
for (unsigned n = 0; n <= arity; ++n)
{
str param;
formal_params.append(
parameter_string(impl, n, f->m_arg_names, cpp_types)
);
// find all the arguments with default values preceeding the arity-n_overloads
if (n && f->m_arg_names)
{
object kv(f->m_arg_names[n-1]);
if (kv && len(kv) == 2)
{
//default argument preceeding the arity-n_overloads
if( n <= arity-n_overloads)
++n_extra_default_args;
}
else
//argument without default, preceeding the arity-n_overloads
if( n <= arity-n_overloads)
n_extra_default_args = 0;
}
}
n_overloads+=n_extra_default_args;
if (!arity && cpp_types)
formal_params.append("void");
str ret_type (formal_params.pop(0));
if (cpp_types )
{
return str(
"%s %s(%s%s%s%s)"
% boost::python::make_tuple // workaround, see top
( ret_type
, f->m_name
, str(",").join(formal_params.slice(0,arity-n_overloads))
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
, str(" [,").join(formal_params.slice(arity-n_overloads,arity))
, std::string(n_overloads,']')
));
}else{
return str(
"%s(%s%s%s%s) -> %s"
% boost::python::make_tuple // workaround, see top
( f->m_name
, str(",").join(formal_params.slice(0,arity-n_overloads))
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
, str(" [,").join(formal_params.slice(arity-n_overloads,arity))
, std::string(n_overloads,']')
, ret_type
));
}
return str(
"%s %s(%s%s%s%s) %s"
% boost::python::make_tuple // workaround, see top
( cpp_types?ret_type:str("")
, f->m_name
, str(",").join(formal_params.slice(0,arity-n_overloads))
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
, str(" [,").join(formal_params.slice(arity-n_overloads,arity))
, std::string(n_overloads,']')
, cpp_types?str(""):ret_type
));
}
namespace detail {
char py_signature_tag[] = "PY signature :";
char cpp_signature_tag[] = "C++ signature :";
}
list function_doc_signature_generator::function_doc_signatures( function const * f)
{
list signatures;
std::vector<function const*> funcs = flatten( f);
std::vector<function const*> split_funcs = split_seq_overloads( funcs, true);
std::vector<function const*>::const_iterator sfi=split_funcs.begin(), fi;
size_t n_overloads=0;
for (fi=funcs.begin(); fi!=funcs.end(); ++fi)
{
if(*sfi == *fi){
if((*fi)->doc())
{
str func_doc = str((*fi)->doc());
int doc_len = len(func_doc);
bool show_py_signature = doc_len >= int(sizeof(detail::py_signature_tag)/sizeof(char)-1)
&& str(detail::py_signature_tag) == func_doc.slice(0, int(sizeof(detail::py_signature_tag)/sizeof(char))-1);
if(show_py_signature)
{
func_doc = str(func_doc.slice(int(sizeof(detail::py_signature_tag)/sizeof(char))-1, _));
doc_len = len(func_doc);
}
bool show_cpp_signature = doc_len >= int(sizeof(detail::cpp_signature_tag)/sizeof(char)-1)
&& str(detail::cpp_signature_tag) == func_doc.slice( 1-int(sizeof(detail::cpp_signature_tag)/sizeof(char)), _);
if(show_cpp_signature)
{
func_doc = str(func_doc.slice(_, 1-int(sizeof(detail::cpp_signature_tag)/sizeof(char))));
doc_len = len(func_doc);
}
str res="\n";
str pad = "\n";
if(show_py_signature)
{
str sig = pretty_signature(*fi, n_overloads,false);
res+=sig;
if(doc_len || show_cpp_signature )res+=" :";
pad+= str(" ");
}
if(doc_len)
{
if(show_py_signature)
res+=pad;
res+= pad.join(func_doc.split("\n"));
}
if( show_cpp_signature)
{
if(len(res)>1)
res+="\n"+pad;
res+=detail::cpp_signature_tag+pad+" "+pretty_signature(*fi, n_overloads,true);
}
signatures.append(res);
}
++sfi;
n_overloads = 0;
}else
++n_overloads ;
}
return signatures;
}
}}}

View File

@ -0,0 +1,495 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object/inheritance.hpp>
#include <boost/python/type_id.hpp>
#include <boost/graph/breadth_first_search.hpp>
#if _MSC_FULL_VER >= 13102171 && _MSC_FULL_VER <= 13102179
# include <boost/graph/reverse_graph.hpp>
#endif
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/reverse_graph.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/bind.hpp>
#include <boost/integer_traits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <queue>
#include <vector>
#include <functional>
//
// Procedure:
//
// The search is a BFS over the space of (type,address) pairs
// guided by the edges of the casting graph whose nodes
// correspond to classes, and whose edges are traversed by
// applying associated cast functions to an address. We use
// vertex distance to the goal node in the cast_graph to rate the
// paths. The vertex distance to any goal node is calculated on
// demand and outdated by the addition of edges to the graph.
namespace boost {
namespace
{
enum edge_cast_t { edge_cast = 8010 };
template <class T> inline void unused_variable(const T&) { }
}
// Install properties
BOOST_INSTALL_PROPERTY(edge, cast);
namespace
{
typedef void*(*cast_function)(void*);
//
// Here we put together the low-level data structures of the
// casting graph representation.
//
typedef python::type_info class_id;
// represents a graph of available casts
#if 0
struct cast_graph
:
#else
typedef
#endif
adjacency_list<vecS,vecS, bidirectionalS, no_property
// edge index property allows us to look up edges in the connectivity matrix
, property<edge_index_t,std::size_t
// The function which casts a void* from the edge's source type
// to its destination type.
, property<edge_cast_t,cast_function> > >
#if 0
{};
#else
cast_graph;
#endif
typedef cast_graph::vertex_descriptor vertex_t;
typedef cast_graph::edge_descriptor edge_t;
struct smart_graph
{
typedef std::vector<std::size_t>::const_iterator node_distance_map;
typedef std::pair<cast_graph::out_edge_iterator
, cast_graph::out_edge_iterator> out_edges_t;
// Return a map of the distances from any node to the given
// target node
node_distance_map distances_to(vertex_t target) const
{
std::size_t n = num_vertices(m_topology);
if (m_distances.size() != n * n)
{
m_distances.clear();
m_distances.resize(n * n, (std::numeric_limits<std::size_t>::max)());
m_known_vertices = n;
}
std::vector<std::size_t>::iterator to_target = m_distances.begin() + n * target;
// this node hasn't been used as a target yet
if (to_target[target] != 0)
{
typedef reverse_graph<cast_graph> reverse_cast_graph;
reverse_cast_graph reverse_topology(m_topology);
to_target[target] = 0;
breadth_first_search(
reverse_topology, target
, visitor(
make_bfs_visitor(
record_distances(
make_iterator_property_map(
to_target
, get(vertex_index, reverse_topology)
# ifdef BOOST_NO_STD_ITERATOR_TRAITS
, *to_target
# endif
)
, on_tree_edge()
))));
}
return to_target;
}
cast_graph& topology() { return m_topology; }
cast_graph const& topology() const { return m_topology; }
smart_graph()
: m_known_vertices(0)
{}
private:
cast_graph m_topology;
mutable std::vector<std::size_t> m_distances;
mutable std::size_t m_known_vertices;
};
smart_graph& full_graph()
{
static smart_graph x;
return x;
}
smart_graph& up_graph()
{
static smart_graph x;
return x;
}
//
// Our index of class types
//
using boost::python::objects::dynamic_id_function;
typedef tuples::tuple<
class_id // static type
, vertex_t // corresponding vertex
, dynamic_id_function // dynamic_id if polymorphic, or 0
>
index_entry_interface;
typedef index_entry_interface::inherited index_entry;
enum { ksrc_static_t, kvertex, kdynamic_id };
typedef std::vector<index_entry> type_index_t;
type_index_t& type_index()
{
static type_index_t x;
return x;
}
template <class Tuple>
struct select1st
{
typedef typename tuples::element<0, Tuple>::type result_type;
result_type const& operator()(Tuple const& x) const
{
return tuples::get<0>(x);
}
};
// map a type to a position in the index
inline type_index_t::iterator type_position(class_id type)
{
typedef index_entry entry;
return std::lower_bound(
type_index().begin(), type_index().end()
, boost::make_tuple(type, vertex_t(), dynamic_id_function(0))
, boost::bind<bool>(std::less<class_id>()
, boost::bind<class_id>(select1st<entry>(), _1)
, boost::bind<class_id>(select1st<entry>(), _2)));
}
inline index_entry* seek_type(class_id type)
{
type_index_t::iterator p = type_position(type);
if (p == type_index().end() || tuples::get<ksrc_static_t>(*p) != type)
return 0;
else
return &*p;
}
// Get the entry for a type, inserting if necessary
inline type_index_t::iterator demand_type(class_id type)
{
type_index_t::iterator p = type_position(type);
if (p != type_index().end() && tuples::get<ksrc_static_t>(*p) == type)
return p;
vertex_t v = add_vertex(full_graph().topology());
vertex_t v2 = add_vertex(up_graph().topology());
unused_variable(v2);
assert(v == v2);
return type_index().insert(p, boost::make_tuple(type, v, dynamic_id_function(0)));
}
// Map a two types to a vertex in the graph, inserting if necessary
typedef std::pair<type_index_t::iterator, type_index_t::iterator>
type_index_iterator_pair;
inline type_index_iterator_pair
demand_types(class_id t1, class_id t2)
{
// be sure there will be no reallocation
type_index().reserve(type_index().size() + 2);
type_index_t::iterator first = demand_type(t1);
type_index_t::iterator second = demand_type(t2);
if (first == second)
++first;
return std::make_pair(first, second);
}
struct q_elt
{
q_elt(std::size_t distance
, void* src_address
, vertex_t target
, cast_function cast
)
: distance(distance)
, src_address(src_address)
, target(target)
, cast(cast)
{}
std::size_t distance;
void* src_address;
vertex_t target;
cast_function cast;
bool operator<(q_elt const& rhs) const
{
return distance < rhs.distance;
}
};
// Optimization:
//
// Given p, src_t, dst_t
//
// Get a pointer pd to the most-derived object
// if it's polymorphic, dynamic_cast to void*
// otherwise pd = p
//
// Get the most-derived typeid src_td
//
// ptrdiff_t offset = p - pd
//
// Now we can keep a cache, for [src_t, offset, src_td, dst_t] of
// the cast transformation function to use on p and the next src_t
// in the chain. src_td, dst_t don't change throughout this
// process. In order to represent unreachability, when a pair is
// found to be unreachable, we stick a 0-returning "dead-cast"
// function in the cache.
// This is needed in a few places below
inline void* identity_cast(void* p)
{
return p;
}
void* search(smart_graph const& g, void* p, vertex_t src, vertex_t dst)
{
// I think this test was thoroughly bogus -- dwa
// If we know there's no path; bail now.
// if (src > g.known_vertices() || dst > g.known_vertices())
// return 0;
smart_graph::node_distance_map d(g.distances_to(dst));
if (d[src] == (std::numeric_limits<std::size_t>::max)())
return 0;
typedef property_map<cast_graph,edge_cast_t>::const_type cast_map;
cast_map casts = get(edge_cast, g.topology());
typedef std::pair<vertex_t,void*> search_state;
typedef std::vector<search_state> visited_t;
visited_t visited;
std::priority_queue<q_elt> q;
q.push(q_elt(d[src], p, src, identity_cast));
while (!q.empty())
{
q_elt top = q.top();
q.pop();
// Check to see if we have a real state
void* dst_address = top.cast(top.src_address);
if (dst_address == 0)
continue;
if (top.target == dst)
return dst_address;
search_state s(top.target,dst_address);
visited_t::iterator pos = std::lower_bound(
visited.begin(), visited.end(), s);
// If already visited, continue
if (pos != visited.end() && *pos == s)
continue;
visited.insert(pos, s); // mark it
// expand it:
smart_graph::out_edges_t edges = out_edges(s.first, g.topology());
for (cast_graph::out_edge_iterator p = edges.first
, finish = edges.second
; p != finish
; ++p
)
{
edge_t e = *p;
q.push(q_elt(
d[target(e, g.topology())]
, dst_address
, target(e, g.topology())
, boost::get(casts, e)));
}
}
return 0;
}
struct cache_element
{
typedef tuples::tuple<
class_id // source static type
, class_id // target type
, std::ptrdiff_t // offset within source object
, class_id // source dynamic type
>::inherited key_type;
cache_element(key_type const& k)
: key(k)
, offset(0)
{}
key_type key;
std::ptrdiff_t offset;
BOOST_STATIC_CONSTANT(
std::ptrdiff_t, not_found = integer_traits<std::ptrdiff_t>::const_min);
bool operator<(cache_element const& rhs) const
{
return this->key < rhs.key;
}
bool unreachable() const
{
return offset == not_found;
}
};
enum { kdst_t = ksrc_static_t + 1, koffset, ksrc_dynamic_t };
typedef std::vector<cache_element> cache_t;
cache_t& cache()
{
static cache_t x;
return x;
}
inline void* convert_type(void* const p, class_id src_t, class_id dst_t, bool polymorphic)
{
// Quickly rule out unregistered types
index_entry* src_p = seek_type(src_t);
if (src_p == 0)
return 0;
index_entry* dst_p = seek_type(dst_t);
if (dst_p == 0)
return 0;
// Look up the dynamic_id function and call it to get the dynamic
// info
boost::python::objects::dynamic_id_t dynamic_id = polymorphic
? tuples::get<kdynamic_id>(*src_p)(p)
: std::make_pair(p, src_t);
// Look in the cache first for a quickie address translation
std::ptrdiff_t offset = (char*)p - (char*)dynamic_id.first;
cache_element seek(boost::make_tuple(src_t, dst_t, offset, dynamic_id.second));
cache_t& c = cache();
cache_t::iterator const cache_pos
= std::lower_bound(c.begin(), c.end(), seek);
// if found in the cache, we're done
if (cache_pos != c.end() && cache_pos->key == seek.key)
{
return cache_pos->offset == cache_element::not_found
? 0 : (char*)p + cache_pos->offset;
}
// If we are starting at the most-derived type, only look in the up graph
smart_graph const& g = polymorphic && dynamic_id.second != src_t
? full_graph() : up_graph();
void* result = search(
g, p, tuples::get<kvertex>(*src_p)
, tuples::get<kvertex>(*dst_p));
// update the cache
c.insert(cache_pos, seek)->offset
= (result == 0) ? cache_element::not_found : (char*)result - (char*)p;
return result;
}
}
namespace python { namespace objects {
BOOST_PYTHON_DECL void* find_dynamic_type(void* p, class_id src_t, class_id dst_t)
{
return convert_type(p, src_t, dst_t, true);
}
BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src_t, class_id dst_t)
{
return convert_type(p, src_t, dst_t, false);
}
BOOST_PYTHON_DECL void add_cast(
class_id src_t, class_id dst_t, cast_function cast, bool is_downcast)
{
// adding an edge will invalidate any record of unreachability in
// the cache.
static std::size_t expected_cache_len = 0;
cache_t& c = cache();
if (c.size() > expected_cache_len)
{
c.erase(std::remove_if(
c.begin(), c.end(),
mem_fn(&cache_element::unreachable))
, c.end());
// If any new cache entries get added, we'll have to do this
// again when the next edge is added
expected_cache_len = c.size();
}
type_index_iterator_pair types = demand_types(src_t, dst_t);
vertex_t src = tuples::get<kvertex>(*types.first);
vertex_t dst = tuples::get<kvertex>(*types.second);
cast_graph* const g[2] = { &up_graph().topology(), &full_graph().topology() };
for (cast_graph*const* p = g + (is_downcast ? 1 : 0); p < g + 2; ++p)
{
edge_t e;
bool added;
tie(e, added) = add_edge(src, dst, **p);
assert(added);
put(get(edge_cast, **p), e, cast);
put(get(edge_index, **p), e, num_edges(full_graph().topology()) - 1);
}
}
BOOST_PYTHON_DECL void register_dynamic_id_aux(
class_id static_id, dynamic_id_function get_dynamic_id)
{
tuples::get<kdynamic_id>(*demand_type(static_id)) = get_dynamic_id;
}
}}} // namespace boost::python::objects

View File

@ -0,0 +1,39 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object/iterator_core.hpp>
#include <boost/python/object/function_object.hpp>
#include <boost/bind.hpp>
#include <boost/mpl/vector/vector10.hpp>
namespace boost { namespace python { namespace objects {
namespace
{
PyObject* identity(PyObject* args_, PyObject*)
{
PyObject* x = PyTuple_GET_ITEM(args_,0);
Py_INCREF(x);
return x;
}
}
BOOST_PYTHON_DECL object const& identity_function()
{
static object result(
function_object(
py_function(&identity, mpl::vector2<PyObject*,PyObject*>())
)
);
return result;
}
void stop_iteration_error()
{
PyErr_SetObject(PyExc_StopIteration, Py_None);
throw_error_already_set();
}
}}} // namespace boost::python::objects

View File

@ -0,0 +1,121 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object/life_support.hpp>
#include <boost/python/detail/none.hpp>
#include <boost/python/refcount.hpp>
namespace boost { namespace python { namespace objects {
struct life_support
{
PyObject_HEAD
PyObject* patient;
};
extern "C"
{
static void
life_support_dealloc(PyObject* self)
{
Py_XDECREF(((life_support*)self)->patient);
self->ob_type->tp_free(self);
}
static PyObject *
life_support_call(PyObject *self, PyObject *arg, PyObject * /*kw*/)
{
// Let the patient die now
Py_XDECREF(((life_support*)self)->patient);
((life_support*)self)->patient = 0;
// Let the weak reference die. This probably kills us.
Py_XDECREF(PyTuple_GET_ITEM(arg, 0));
return ::boost::python::detail::none();
}
}
PyTypeObject life_support_type = {
PyVarObject_HEAD_INIT(NULL, 0)//(&PyType_Type)
const_cast<char*>("Boost.Python.life_support"),
sizeof(life_support),
0,
life_support_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, //(reprfunc)func_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
life_support_call, /* tp_call */
0, /* tp_str */
0, // PyObject_GenericGetAttr, /* tp_getattro */
0, // PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
0, /* tp_doc */
0, // (traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, //offsetof(PyLife_SupportObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, // func_memberlist, /* tp_members */
0, //func_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
#if PYTHON_API_VERSION >= 1012
0 /* tp_del */
#endif
};
PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient)
{
if (nurse == Py_None || nurse == patient)
return nurse;
if (Py_TYPE(&life_support_type) == 0)
{
Py_TYPE(&life_support_type) = &PyType_Type;
PyType_Ready(&life_support_type);
}
life_support* system = PyObject_New(life_support, &life_support_type);
if (!system)
return 0;
system->patient = 0;
// We're going to leak this reference, but don't worry; the
// life_support system decrements it when the nurse dies.
PyObject* weakref = PyWeakref_NewRef(nurse, (PyObject*)system);
// weakref has either taken ownership, or we have to release it
// anyway
Py_DECREF(system);
if (!weakref)
return 0;
system->patient = patient;
Py_XINCREF(patient); // hang on to the patient until death
return weakref;
}
}}} // namespace boost::python::objects

View File

@ -0,0 +1,78 @@
// (C) Copyright R.W. Grosse-Kunstleve 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/make_function.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/list.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/str.hpp>
namespace boost { namespace python {
namespace {
tuple instance_reduce(object instance_obj)
{
list result;
object instance_class(instance_obj.attr("__class__"));
result.append(instance_class);
object none;
if (!getattr(instance_obj, "__safe_for_unpickling__", none))
{
str type_name(getattr(instance_class, "__name__"));
str module_name(getattr(instance_class, "__module__", object("")));
if (module_name)
module_name += ".";
PyErr_SetObject(
PyExc_RuntimeError,
( "Pickling of \"%s\" instances is not enabled"
" (http://www.boost.org/libs/python/doc/v2/pickle.html)"
% (module_name+type_name)).ptr()
);
throw_error_already_set();
}
object getinitargs = getattr(instance_obj, "__getinitargs__", none);
tuple initargs;
if (!getinitargs.is_none()) {
initargs = tuple(getinitargs());
}
result.append(initargs);
object getstate = getattr(instance_obj, "__getstate__", none);
object instance_dict = getattr(instance_obj, "__dict__", none);
long len_instance_dict = 0;
if (!instance_dict.is_none()) {
len_instance_dict = len(instance_dict);
}
if (!getstate.is_none()) {
if (len_instance_dict > 0) {
object getstate_manages_dict = getattr(
instance_obj, "__getstate_manages_dict__", none);
if (getstate_manages_dict.is_none()) {
PyErr_SetString(PyExc_RuntimeError,
"Incomplete pickle support"
" (__getstate_manages_dict__ not set)");
throw_error_already_set();
}
}
result.append(getstate());
}
else if (len_instance_dict > 0) {
result.append(instance_dict);
}
return tuple(result);
}
} // namespace
object const& make_instance_reduce_function()
{
static object result(&instance_reduce);
return result;
}
}} // namespace boost::python

View File

@ -0,0 +1,48 @@
// Copyright Eric Niebler 2005.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Credits:
// Andreas Kl\:ockner for fixing increment() to handle
// error conditions.
#include <boost/python/object.hpp>
#include <boost/python/handle.hpp>
#include <boost/python/object/stl_iterator_core.hpp>
namespace boost { namespace python { namespace objects
{
stl_input_iterator_impl::stl_input_iterator_impl()
: it_()
, ob_()
{
}
stl_input_iterator_impl::stl_input_iterator_impl(boost::python::object const &ob)
: it_(ob.attr("__iter__")())
, ob_()
{
this->increment();
}
void stl_input_iterator_impl::increment()
{
this->ob_ = boost::python::handle<>(
boost::python::allow_null(PyIter_Next(this->it_.ptr())));
if (PyErr_Occurred())
throw boost::python::error_already_set();
}
bool stl_input_iterator_impl::equal(stl_input_iterator_impl const &that) const
{
return !this->ob_ == !that.ob_;
}
boost::python::handle<> const &stl_input_iterator_impl::current() const
{
return this->ob_;
}
}}} // namespace boost::python::objects

View File

@ -0,0 +1,85 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object_operators.hpp>
#include <boost/python/detail/raw_pyobject.hpp>
namespace boost { namespace python { namespace api {
# define BOOST_PYTHON_COMPARE_OP(op, opid) \
BOOST_PYTHON_DECL object operator op(object const& l, object const& r) \
{ \
return object( \
detail::new_reference( \
PyObject_RichCompare( \
l.ptr(), r.ptr(), opid)) \
); \
}
BOOST_PYTHON_COMPARE_OP(>, Py_GT)
BOOST_PYTHON_COMPARE_OP(>=, Py_GE)
BOOST_PYTHON_COMPARE_OP(<, Py_LT)
BOOST_PYTHON_COMPARE_OP(<=, Py_LE)
BOOST_PYTHON_COMPARE_OP(==, Py_EQ)
BOOST_PYTHON_COMPARE_OP(!=, Py_NE)
# undef BOOST_PYTHON_COMPARE_OP
#define BOOST_PYTHON_BINARY_OPERATOR(op, name) \
BOOST_PYTHON_DECL object operator op(object const& l, object const& r) \
{ \
return object( \
detail::new_reference( \
PyNumber_##name(l.ptr(), r.ptr())) \
); \
}
BOOST_PYTHON_BINARY_OPERATOR(+, Add)
BOOST_PYTHON_BINARY_OPERATOR(-, Subtract)
BOOST_PYTHON_BINARY_OPERATOR(*, Multiply)
#if PY_VERSION_HEX >= 0x03000000
// We choose FloorDivide instead of TrueDivide to keep the semantic
// conform with C/C++'s '/' operator
BOOST_PYTHON_BINARY_OPERATOR(/, FloorDivide)
#else
BOOST_PYTHON_BINARY_OPERATOR(/, Divide)
#endif
BOOST_PYTHON_BINARY_OPERATOR(%, Remainder)
BOOST_PYTHON_BINARY_OPERATOR(<<, Lshift)
BOOST_PYTHON_BINARY_OPERATOR(>>, Rshift)
BOOST_PYTHON_BINARY_OPERATOR(&, And)
BOOST_PYTHON_BINARY_OPERATOR(^, Xor)
BOOST_PYTHON_BINARY_OPERATOR(|, Or)
#undef BOOST_PYTHON_BINARY_OPERATOR
#define BOOST_PYTHON_INPLACE_OPERATOR(op, name) \
BOOST_PYTHON_DECL object& operator op##=(object& l, object const& r) \
{ \
return l = object( \
(detail::new_reference) \
PyNumber_InPlace##name(l.ptr(), r.ptr())); \
}
BOOST_PYTHON_INPLACE_OPERATOR(+, Add)
BOOST_PYTHON_INPLACE_OPERATOR(-, Subtract)
BOOST_PYTHON_INPLACE_OPERATOR(*, Multiply)
#if PY_VERSION_HEX >= 0x03000000
// Same reason as above for choosing FloorDivide instead of TrueDivide
BOOST_PYTHON_INPLACE_OPERATOR(/, FloorDivide)
#else
BOOST_PYTHON_INPLACE_OPERATOR(/, Divide)
#endif
BOOST_PYTHON_INPLACE_OPERATOR(%, Remainder)
BOOST_PYTHON_INPLACE_OPERATOR(<<, Lshift)
BOOST_PYTHON_INPLACE_OPERATOR(>>, Rshift)
BOOST_PYTHON_INPLACE_OPERATOR(&, And)
BOOST_PYTHON_INPLACE_OPERATOR(^, Xor)
BOOST_PYTHON_INPLACE_OPERATOR(|, Or)
#undef BOOST_PYTHON_INPLACE_OPERATOR
object::object(handle<> const& x)
: object_base(python::incref(python::expect_non_null(x.get())))
{}
}}} // namespace boost::python

View File

@ -0,0 +1,197 @@
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object_protocol.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/object.hpp>
#include <boost/python/ssize_t.hpp>
namespace boost { namespace python { namespace api {
BOOST_PYTHON_DECL object getattr(object const& target, object const& key)
{
return object(detail::new_reference(PyObject_GetAttr(target.ptr(), key.ptr())));
}
BOOST_PYTHON_DECL object getattr(object const& target, object const& key, object const& default_)
{
PyObject* result = PyObject_GetAttr(target.ptr(), key.ptr());
if (result == NULL && PyErr_ExceptionMatches(PyExc_AttributeError))
{
PyErr_Clear();
return default_;
}
return object(detail::new_reference(result));
}
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value)
{
if (PyObject_SetAttr(target.ptr(), key.ptr(), value.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void delattr(object const& target, object const& key)
{
if (PyObject_DelAttr(target.ptr(), key.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL object getattr(object const& target, char const* key)
{
return object(
detail::new_reference(
PyObject_GetAttrString(target.ptr(), const_cast<char*>(key))
));
}
BOOST_PYTHON_DECL object getattr(object const& target, char const* key, object const& default_)
{
PyObject* result = PyObject_GetAttrString(target.ptr(), const_cast<char*>(key));
if (result == NULL && PyErr_ExceptionMatches(PyExc_AttributeError))
{
PyErr_Clear();
return default_;
}
return object(detail::new_reference(result));
}
BOOST_PYTHON_DECL void setattr(object const& target, char const* key, object const& value)
{
if (PyObject_SetAttrString(
target.ptr(), const_cast<char*>(key), value.ptr()) == -1
)
{
throw_error_already_set();
}
}
BOOST_PYTHON_DECL void delattr(object const& target, char const* key)
{
if (PyObject_DelAttrString(
target.ptr(), const_cast<char*>(key)) == -1
)
{
throw_error_already_set();
}
}
BOOST_PYTHON_DECL object getitem(object const& target, object const& key)
{
return object(detail::new_reference(
PyObject_GetItem(target.ptr(), key.ptr())));
}
BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value)
{
if (PyObject_SetItem(target.ptr(), key.ptr(), value.ptr()) == -1)
throw_error_already_set();
}
BOOST_PYTHON_DECL void delitem(object const& target, object const& key)
{
if (PyObject_DelItem(target.ptr(), key.ptr()) == -1)
throw_error_already_set();
}
namespace // slicing code copied directly out of the Python implementation
{
#undef ISINT
#define ISINT(x) ((x) == NULL || PyInt_Check(x) || PyLong_Check(x))
static PyObject *
apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
{
#if PY_VERSION_HEX < 0x03000000
PyTypeObject *tp = u->ob_type;
PySequenceMethods *sq = tp->tp_as_sequence;
if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) {
ssize_t ilow = 0, ihigh = ssize_t_max;
if (!_PyEval_SliceIndex(v, &ilow))
return NULL;
if (!_PyEval_SliceIndex(w, &ihigh))
return NULL;
return PySequence_GetSlice(u, ilow, ihigh);
}
else
#endif
{
PyObject *slice = PySlice_New(v, w, NULL);
if (slice != NULL) {
PyObject *res = PyObject_GetItem(u, slice);
Py_DECREF(slice);
return res;
}
else
return NULL;
}
}
static int
assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
/* u[v:w] = x */
{
#if PY_VERSION_HEX < 0x03000000
PyTypeObject *tp = u->ob_type;
PySequenceMethods *sq = tp->tp_as_sequence;
if (sq && sq->sq_slice && ISINT(v) && ISINT(w)) {
ssize_t ilow = 0, ihigh = ssize_t_max;
if (!_PyEval_SliceIndex(v, &ilow))
return -1;
if (!_PyEval_SliceIndex(w, &ihigh))
return -1;
if (x == NULL)
return PySequence_DelSlice(u, ilow, ihigh);
else
return PySequence_SetSlice(u, ilow, ihigh, x);
}
else
#endif
{
PyObject *slice = PySlice_New(v, w, NULL);
if (slice != NULL) {
int res;
if (x != NULL)
res = PyObject_SetItem(u, slice, x);
else
res = PyObject_DelItem(u, slice);
Py_DECREF(slice);
return res;
}
else
return -1;
}
}
}
BOOST_PYTHON_DECL object getslice(object const& target, handle<> const& begin, handle<> const& end)
{
return object(
detail::new_reference(
apply_slice(target.ptr(), begin.get(), end.get())));
}
BOOST_PYTHON_DECL void setslice(object const& target, handle<> const& begin, handle<> const& end, object const& value)
{
if (assign_slice(
target.ptr(), begin.get(), end.get(), value.ptr()) == -1
)
{
throw_error_already_set();
}
}
BOOST_PYTHON_DECL void delslice(object const& target, handle<> const& begin, handle<> const& end)
{
if (assign_slice(
target.ptr(), begin.get(), end.get(), 0) == -1
)
{
throw_error_already_set();
}
}
}}} // namespace boost::python::api

View File

@ -0,0 +1,37 @@
#include "boost/python/slice.hpp"
// Copyright (c) 2004 Jonathan Brandmeyer
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
namespace boost { namespace python { namespace detail {
slice_base::slice_base(PyObject* start, PyObject* stop, PyObject* step)
: object(detail::new_reference( PySlice_New(start, stop, step)))
{
}
object
slice_base::start() const
{
return object( detail::borrowed_reference(
((PySliceObject*)this->ptr())->start));
}
object
slice_base::stop() const
{
return object( detail::borrowed_reference(
((PySliceObject*)this->ptr())->stop));
}
object
slice_base::step() const
{
return object( detail::borrowed_reference(
((PySliceObject*)this->ptr())->step));
}
} } } // !namespace boost::python::detail

419
pykd/boost.python/str.cpp Normal file
View File

@ -0,0 +1,419 @@
// Copyright David Abrahams 2004. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/str.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/ssize_t.hpp>
namespace boost { namespace python { namespace detail {
detail::new_reference str_base::call(object const& arg_)
{
return (detail::new_reference)PyObject_CallFunction(
#if PY_VERSION_HEX >= 0x03000000
(PyObject*)&PyUnicode_Type,
#else
(PyObject*)&PyString_Type,
#endif
const_cast<char*>("(O)"),
arg_.ptr());
}
str_base::str_base()
: object(detail::new_reference(
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromString("")
#else
::PyString_FromString("")
#endif
))
{}
str_base::str_base(const char* s)
: object(detail::new_reference(
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromString(s)
#else
::PyString_FromString(s)
#endif
))
{}
namespace {
ssize_t str_size_as_py_ssize_t(std::size_t n)
{
if (n > static_cast<std::size_t>(ssize_t_max))
{
throw std::range_error("str size > ssize_t_max");
}
return static_cast<ssize_t>(n);
}
} // namespace <anonymous>
str_base::str_base(char const* start, char const* finish)
: object(
detail::new_reference(
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
(start, str_size_as_py_ssize_t(finish - start))
)
)
{}
str_base::str_base(char const* start, std::size_t length) // new str
: object(
detail::new_reference(
#if PY_VERSION_HEX >= 0x03000000
::PyUnicode_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
( start, str_size_as_py_ssize_t(length) )
)
)
{}
str_base::str_base(object_cref other)
: object(str_base::call(other))
{}
#define BOOST_PYTHON_FORMAT_OBJECT(z, n, data) "O"
#define BOOST_PYTHON_OBJECT_PTR(z, n, data) , x##n .ptr()
#define BOOST_PYTHON_DEFINE_STR_METHOD(name, arity) \
str str_base:: name ( BOOST_PP_ENUM_PARAMS(arity, object_cref x) ) const \
{ \
return str(new_reference( \
expect_non_null( \
PyObject_CallMethod( \
this->ptr(), const_cast<char*>( #name ), \
const_cast<char*>( \
"(" BOOST_PP_REPEAT(arity, BOOST_PYTHON_FORMAT_OBJECT, _) ")") \
BOOST_PP_REPEAT_1(arity, BOOST_PYTHON_OBJECT_PTR, _))))); \
}
BOOST_PYTHON_DEFINE_STR_METHOD(capitalize, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(center, 1)
long str_base::count(object_cref sub) const
{
return extract<long>(this->attr("count")(sub));
}
long str_base::count(object_cref sub, object_cref start) const
{
return extract<long>(this->attr("count")(sub,start));
}
long str_base::count(object_cref sub, object_cref start, object_cref end) const
{
return extract<long>(this->attr("count")(sub,start,end));
}
#if PY_VERSION_HEX < 0x03000000
object str_base::decode() const
{
return this->attr("decode")();
}
object str_base::decode(object_cref encoding) const
{
return this->attr("decode")(encoding);
}
object str_base::decode(object_cref encoding, object_cref errors) const
{
return this->attr("decode")(encoding,errors);
}
#endif
object str_base::encode() const
{
return this->attr("encode")();
}
object str_base::encode(object_cref encoding) const
{
return this->attr("encode")(encoding);
}
object str_base::encode(object_cref encoding, object_cref errors) const
{
return this->attr("encode")(encoding,errors);
}
#if PY_VERSION_HEX >= 0x03000000
#define _BOOST_PYTHON_ASLONG PyLong_AsLong
#else
#define _BOOST_PYTHON_ASLONG PyInt_AsLong
#endif
bool str_base::endswith(object_cref suffix) const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::endswith(object_cref suffix, object_cref start) const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix,start).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::endswith(object_cref suffix, object_cref start, object_cref end) const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix,start,end).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
BOOST_PYTHON_DEFINE_STR_METHOD(expandtabs, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(expandtabs, 1)
long str_base::find(object_cref sub) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::find(object_cref sub, object_cref start) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::find(object_cref sub, object_cref start, object_cref end) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start,end).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::index(object_cref sub) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::index(object_cref sub, object_cref start) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::index(object_cref sub, object_cref start, object_cref end) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start,end).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::isalnum() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("isalnum")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::isalpha() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("isalpha")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::isdigit() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("isdigit")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::islower() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("islower")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::isspace() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("isspace")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::istitle() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("istitle")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::isupper() const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("isupper")().ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
BOOST_PYTHON_DEFINE_STR_METHOD(join, 1)
BOOST_PYTHON_DEFINE_STR_METHOD(ljust, 1)
BOOST_PYTHON_DEFINE_STR_METHOD(lower, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(lstrip, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(replace, 2)
BOOST_PYTHON_DEFINE_STR_METHOD(replace, 3)
long str_base::rfind(object_cref sub) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::rfind(object_cref sub, object_cref start) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::rfind(object_cref sub, object_cref start, object_cref end) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start,end).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::rindex(object_cref sub) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::rindex(object_cref sub, object_cref start) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
long str_base::rindex(object_cref sub, object_cref start, object_cref end) const
{
long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start,end).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
BOOST_PYTHON_DEFINE_STR_METHOD(rjust, 1)
BOOST_PYTHON_DEFINE_STR_METHOD(rstrip, 0)
list str_base::split() const
{
return list(this->attr("split")());
}
list str_base::split(object_cref sep) const
{
return list(this->attr("split")(sep));
}
list str_base::split(object_cref sep, object_cref maxsplit) const
{
return list(this->attr("split")(sep,maxsplit));
}
list str_base::splitlines() const
{
return list(this->attr("splitlines")());
}
list str_base::splitlines(object_cref keepends) const
{
return list(this->attr("splitlines")(keepends));
}
bool str_base::startswith(object_cref prefix) const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::startswith(object_cref prefix, object_cref start) const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
bool str_base::startswith(object_cref prefix, object_cref start, object_cref end) const
{
bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start,end).ptr());
if (PyErr_Occurred())
throw_error_already_set();
return result;
}
#undef _BOOST_PYTHON_ASLONG
BOOST_PYTHON_DEFINE_STR_METHOD(strip, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(swapcase, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(title, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(translate, 1)
BOOST_PYTHON_DEFINE_STR_METHOD(translate, 2)
BOOST_PYTHON_DEFINE_STR_METHOD(upper, 0)
static struct register_str_pytype_ptr
{
register_str_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::str>())
)
#if PY_VERSION_HEX >= 0x03000000
.m_class_object = &PyUnicode_Type;
#else
.m_class_object = &PyString_Type;
#endif
}
}register_str_pytype_ptr_;
}}} // namespace boost::python

View File

@ -0,0 +1,35 @@
// Copyright David Abrahams 2004.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/tuple.hpp>
namespace boost { namespace python { namespace detail {
detail::new_reference tuple_base::call(object const& arg_)
{
return (detail::new_reference)PyObject_CallFunction(
(PyObject*)&PyTuple_Type, const_cast<char*>("(O)"),
arg_.ptr());
}
tuple_base::tuple_base()
: object(detail::new_reference(PyTuple_New(0)))
{}
tuple_base::tuple_base(object_cref sequence)
: object(call(sequence))
{}
static struct register_tuple_pytype_ptr
{
register_tuple_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::tuple>())
).m_class_object = &PyTuple_Type;
}
}register_tuple_pytype_ptr_;
}}} // namespace boost::python

View File

@ -0,0 +1,66 @@
// Copyright David Abrahams 2004. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/wrapper.hpp>
namespace boost { namespace python {
namespace detail
{
override wrapper_base::get_override(
char const* name
, PyTypeObject* class_object
) const
{
if (this->m_self)
{
if (handle<> m = handle<>(
python::allow_null(
::PyObject_GetAttrString(
this->m_self, const_cast<char*>(name))))
)
{
PyObject* borrowed_f = 0;
if (
PyMethod_Check(m.get())
&& ((PyMethodObject*)m.get())->im_self == this->m_self
&& class_object->tp_dict != 0
)
{
borrowed_f = ::PyDict_GetItemString(
class_object->tp_dict, const_cast<char*>(name));
}
if (borrowed_f != ((PyMethodObject*)m.get())->im_func)
return override(m);
}
}
return override(handle<>(detail::none()));
}
}
#if 0
namespace converter
{
PyObject* BOOST_PYTHON_DECL do_polymorphic_ref_to_python(
python::detail::wrapper_base const volatile* x, type_info src
)
{
if (x == 0)
{
::PyErr_Format(
PyExc_TypeError
, "Attempting to returning pointer or reference to instance of %s\n"
"for which no corresponding Python object exists. Wrap this function"
"with a return return value policy"
)
}
}
}
#endif
}} // namespace boost::python::detail

View File

@ -1,7 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="python2" version="2.7.18" allowedVersions="[2.7.12,2.8.0)" targetFramework="native" /> <package id="boost" version="1.67.0.0" targetFramework="native" />
<package id="python2x86" version="2.7.18" allowedVersions="[2.7.12,2.8.0)" targetFramework="native" /> <package id="boost_atomic-src" version="1.67.0.0" targetFramework="native" />
<package id="python" version="3.13.1" allowedVersions="[3.5.2,3.14.0)" targetFramework="native" /> <package id="boost_chrono-src" version="1.67.0.0" targetFramework="native" />
<package id="pythonx86" version="3.13.1" allowedVersions="[3.5.2,3.14.0)" targetFramework="native" /> <package id="boost_date_time-src" version="1.67.0.0" targetFramework="native" />
<package id="boost_regex-src" version="1.67.0.0" targetFramework="native" />
<package id="boost_system-src" version="1.67.0.0" targetFramework="native" />
<package id="boost_thread-src" version="1.67.0.0" targetFramework="native" />
<package id="Python27" version="2.7.6" targetFramework="Native" />
<package id="Python35" version="3.5.1.1" targetFramework="Native" />
<package id="Python36" version="3.6.0" targetFramework="Native" />
<package id="Python37" version="1.0.0.1" targetFramework="Native" />
<package id="Python38" version="3.8.0" targetFramework="Native" />
<package id="Python39" version="3.9.0" targetFramework="Native" />
<package id="python" version="3.10.10" allowedVersions="[3.10.0,3.11.0)" targetFramework="native" />
<package id="pythonx86" version="3.10.10" allowedVersions="[3.10.0,3.11.0)" targetFramework="native" />
<package id="clang-cmake" version="6.0.0.1" targetFramework="Native" />
<package id="llvm-cmake" version="6.0.0.1" targetFramework="Native" />
</packages> </packages>

File diff suppressed because it is too large Load Diff

View File

@ -131,6 +131,186 @@
<ClCompile Include="pytagged.cpp"> <ClCompile Include="pytagged.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_atomic-src.lockpool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_chrono-src.chrono.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_chrono-src.process_cpu_clocks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_chrono-src.thread_clock.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\gregorian\boost_date_time-src.gregorian.date_generators.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\gregorian\boost_date_time-src.gregorian.gregorian_types.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\gregorian\boost_date_time-src.gregorian.greg_month.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\gregorian\boost_date_time-src.gregorian.greg_weekday.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\posix_time\boost_date_time-src.posix_time.posix_time_types.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.cpp_regex_traits.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.cregex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.c_regex_traits.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.fileiter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.icu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.instances.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.posix_api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.regex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.regex_debug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.regex_raw_buffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.regex_traits_defaults.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.static_mutex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.w32_regex_traits.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.wc_regex_traits.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.wide_posix_api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.winstances.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_system-src.error_code.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\win32\boost_thread-src.win32.thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\win32\boost_thread-src.win32.thread_primitives.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\win32\boost_thread-src.win32.tss_dll.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\win32\boost_thread-src.win32.tss_pe.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_thread-src.future.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_thread-src.tss_null.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.dict.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.errors.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.exec.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.import.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.list.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.long.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.module.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.object_operators.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.object_protocol.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.slice.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.str.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.tuple.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\boost_python-src.wrapper.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\converter\boost_python-src.converter.arg_to_python_base.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\converter\boost_python-src.converter.builtin_converters.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\converter\boost_python-src.converter.from_python.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\converter\boost_python-src.converter.registry.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\converter\boost_python-src.converter.type_id.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.class.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.enum.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.function.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.function_doc_signature.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.inheritance.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.iterator.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.life_support.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.pickle_support.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="boost.python\object\boost_python-src.object.stl_iterator.cpp">
<Filter>boost.python</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\lib\native\src\boost_regex-src.usinstances.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="pykd.def"> <None Include="pykd.def">

@ -1 +0,0 @@
Subproject commit e78e6c8f691be922ea1ac9e98998ebcc4488c93d

View File

@ -1 +0,0 @@
0.3.4.15

View File

@ -1,19 +1,31 @@
@ECHO OFF py -2.7 setup.py bdist_zip --plat-name=win32
SETLOCAL EnableDelayedExpansion py -2.7 setup.py bdist_zip --plat-name=win-amd64
py -2.7 setup.py bdist_wheel --plat-name=win32 --python-tag=cp27
py -2.7 setup.py bdist_wheel --plat-name=win-amd64 --python-tag=cp27
set py_list=2.7 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 py -3.5 setup.py bdist_zip --plat-name=win32
set plat_list=win32 x64 py -3.5 setup.py bdist_zip --plat-name=win-amd64
py -3.5 setup.py bdist_wheel --plat-name=win32 --python-tag=cp35
py -3.5 setup.py bdist_wheel --plat-name=win-amd64 --python-tag=cp35
REM Build wheel and zip py -3.6 setup.py bdist_zip --plat-name=win32
REM py -<py version> setup.py bdist_wheel --plat-name=<plat-name> [bdist_zip] py -3.6 setup.py bdist_zip --plat-name=win-amd64
REM py -<py version> setup.py bdist_wheel --plat-name=<plat-name> [--build-base=build_dir] [--dist-dir=bdist_dir] [--egg-base=egg_dir] [bdist_zip] py -3.6 setup.py bdist_wheel --plat-name=win32 --python-tag=cp36
py -3.6 setup.py bdist_wheel --plat-name=win-amd64 --python-tag=cp36
for %%a in (%py_list%) do ( py -3.7 setup.py bdist_zip --plat-name=win32
for %%b in (%plat_list%) do ( py -3.7 setup.py bdist_zip --plat-name=win-amd64
set py_ver=%%a py -3.7 setup.py bdist_wheel --plat-name=win32 --python-tag=cp37
set plat=%%b py -3.7 setup.py bdist_wheel --plat-name=win-amd64 --python-tag=cp37
py -!py_ver! -m pip install --user gitpython setuptools wheel
py -!py_ver! setup.py bdist_wheel --plat-name=!plat! bdist_zip py -3.8 setup.py bdist_zip --plat-name=win32
) py -3.8 setup.py bdist_zip --plat-name=win-amd64
) py -3.8 setup.py bdist_wheel --plat-name=win32 --python-tag=cp38
exit py -3.8 setup.py bdist_wheel --plat-name=win-amd64 --python-tag=cp38
py -3.9 setup.py bdist_zip --plat-name=win32
py -3.9 setup.py bdist_zip --plat-name=win-amd64
py -3.9 setup.py bdist_wheel --plat-name=win32 --python-tag=cp39
py -3.9 setup.py bdist_wheel --plat-name=win-amd64 --python-tag=cp39
py setup.py bdist_pdb

View File

@ -1,177 +1,131 @@
import os from setuptools import setup
from wheel.bdist_wheel import bdist_wheel
import os
import shutil import shutil
import zipfile import zipfile
import sys import sys
import argparse import itertools
import re
import setuptools
import git
if sys.version_info.major == 2:
import pathlib2
_name = "pykd" _name = "pykd"
_desc = "python windbg extension" _desc = "python windbg extension"
_version = '0.3.4.15'
def main(): def getReleaseSrc():
parser = argparse.ArgumentParser() return 'Release_%d.%d' % sys.version_info[0:2]
parser.add_argument('--plat-name', choices = ['win32', 'win-amd64', 'x86', 'x64'], required = True, type = str.lower)
parser.add_argument('--build-base', type = str, required = False)
parser.add_argument('--dist-dir', type = str, required = False)
parser.add_argument('--egg-base', type = str, required = False)
args, unkonwn_args = parser.parse_known_args()
platform = '' if "bdist_wheel" in sys.argv:
platform_alt = ''
configuration = 'Release' # remove build catalog
if (args.plat_name == 'win32') or (args.plat_name == 'x86'): build_dir = os.path.join(os.path.curdir, 'build' )
args.plat_name = 'win32' if os.path.exists(build_dir):
platform = 'win32' shutil.rmtree(build_dir)
platform_alt = 'x86'
elif (args.plat_name == 'win-amd64') or (args.plat_name == 'x64'): # make package catalog
args.plat_name = 'win-amd64' package_dir = os.path.join(os.path.curdir, _name )
platform = 'x64' if os.path.exists(package_dir):
platform_alt = 'x64' shutil.rmtree(package_dir)
os.mkdir(package_dir)
shutil.copy("__init__.py", package_dir)
bin_dir = os.path.join( os.path.curdir, '..', 'kdlibcpp/bin')
pykd_dir = os.path.join( os.path.curdir, '..', 'out')
if "--plat-name=win32" in sys.argv:
bin_dir = os.path.join( bin_dir, 'x86')
pykd_dir = os.path.join(pykd_dir, 'Win32', getReleaseSrc())
elif "--plat-name=win-amd64" in sys.argv:
bin_dir = os.path.join( bin_dir, 'x64')
pykd_dir = os.path.join(pykd_dir, 'X64', getReleaseSrc())
else: else:
print("Unsupported platform %s" %(args.plat_name)) assert(0)
exit
python_tag = "cp%d%d" %(sys.version_info.major, sys.version_info.minor) assert(os.path.isdir(bin_dir))
dir_solution = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) for binFile in [ f for f in os.listdir(bin_dir) if not os.path.isdir(f) ]:
shutil.copy( os.path.join(bin_dir, binFile), os.path.join(package_dir, binFile) )
_version = '' shutil.copy( os.path.join(pykd_dir, 'pykd.pyd'), os.path.join(package_dir, 'pykd.pyd') )
# Using VERSION file on releaase branch setup(
if os.path.isfile(os.path.join(os.path.dirname(__file__), 'VERSION')): name = _name,
with open(os.path.join(os.path.dirname(__file__), 'VERSION'), 'r') as verf: version = _version,
_version = verf.readline() description = _desc,
# cmdclass = { 'bdist_wheel' : bdist_wheel },
# Using versions from pykdver.h and branch HEAD packages = ['pykd'],
if _version == '': package_dir = {'pykd': package_dir},
versions = ['', '', '', ''] package_data = { 'pykd' :["*.pyd", "*.dll"]},
if os.path.isfile(os.path.join(dir_solution, 'pykd', 'pykdver.h')): include_package_data=True,
with open(os.path.join(os.path.join(dir_solution, 'pykd', 'pykdver.h')), 'r') as verf: zip_safe = False
lines = verf.readlines()
for line in lines:
ver_raw_match = re.findall(r"^#define\s*PYKD_VERSION_MAJOR\s*(.*)$", line)
if (len(ver_raw_match)):
versions[0] = ver_raw_match[0]
continue
ver_raw_match = re.findall(r"^#define\s*PYKD_VERSION_MINOR\s*(.*)$", line)
if (len(ver_raw_match)):
versions[1] = ver_raw_match[0]
continue
ver_raw_match = re.findall(r"^#define\s*PYKD_VERSION_SUBVERSION\s*(.*)$", line)
if (len(ver_raw_match)):
versions[2] = ver_raw_match[0]
continue
ver_raw_match = re.findall(r"^#define\s*PYKD_VERSION_BUILDNO\s*(.*)$", line)
if (len(ver_raw_match)):
versions[3] = ver_raw_match[0]
continue
_version = "%s.%s.%s.%s+g" % (versions[0], versions[1], versions[2], versions[3])
try:
repo = git.Repo(dir_solution)
_version = "%s%s" % (_version, repo.git.rev_parse(repo.head, short = True))
except:
print("Skip using HEAD SHA as non git repo")
dir_dbgsdk_bin = os.path.join(dir_solution, 'kdlibcpp', 'WinDbgExt', 'bin', platform_alt)
if not os.path.exists(dir_dbgsdk_bin):
print("DbgSDK bin path %s doesn't exist" %(dir_dbgsdk_bin))
sys.exit()
dir_pykd_bin = os.path.join(dir_solution, 'Out', platform, "%s_%d.%d" %(configuration, sys.version_info.major, sys.version_info.minor))
if not os.path.exists(os.path.join(dir_pykd_bin, 'pykd.pyd')):
print("pykd.pyd doesn't exist in %s" %(dir_pykd_bin))
sys.exit()
if args.build_base is not None:
dir_build_base = args.build_base
else:
dir_build_base = os.path.join(dir_solution, 'Obj', 'Wheel', platform, "%s_%d.%d" %(configuration, sys.version_info.major, sys.version_info.minor), 'setuptools')
if args.dist_dir is not None:
dir_dist_wheel = args.dist_dir
else:
dir_dist_wheel = dir_pykd_bin
if args.egg_base is not None:
dir_egg_base = args.egg_base
else:
dir_egg_base = dir_build_base
dir_wheel_package = os.path.join(dir_build_base, _name)
if os.path.exists(dir_build_base):
shutil.rmtree(dir_build_base)
if sys.version_info.major == 2:
pathlib2.Path(dir_build_base).mkdir(exist_ok = True, parents = True)
else:
os.makedirs(dir_build_base, exist_ok = True)
if os.path.exists(dir_wheel_package):
shutil.rmtree(dir_wheel_package)
if sys.version_info.major == 2:
pathlib2.Path(dir_wheel_package).mkdir(exist_ok = True, parents = True)
else:
os.makedirs(dir_wheel_package, exist_ok = True)
print("Using DbgSDK from %s" %(dir_dbgsdk_bin))
print("Using pykd binary from %s" %(dir_pykd_bin))
print("Using build directory as %s" %(dir_build_base))
print("Using egg info directory as %s" %(dir_egg_base))
print("Using Wheel output directory as %s" %(dir_dist_wheel))
shutil.copy2(os.path.join(dir_solution, 'setup', '__init__.py'), dir_wheel_package)
shutil.copy2(os.path.join(dir_pykd_bin, 'pykd.pyd'), dir_wheel_package)
shutil.copy2(os.path.join(dir_solution, 'Obj', 'pykd', platform, "%s_%d.%d" %(configuration, sys.version_info.major, sys.version_info.minor), 'msdia140.dll'), dir_wheel_package)
for dbgSdkBin in [ f for f in os.listdir(dir_dbgsdk_bin) if not os.path.isdir(f) ]:
shutil.copy2(os.path.join(dir_dbgsdk_bin, dbgSdkBin), dir_wheel_package)
if 'bdist_wheel' in unkonwn_args:
print("Building bdist_wheel ...")
sys.argv = ['setup.py']
sys.argv.append("build")
sys.argv.append("--build-base=%s" %(dir_build_base))
sys.argv.append("--plat-name=%s" %(args.plat_name))
sys.argv.append("bdist_wheel")
sys.argv.append("--dist-dir=%s" %(dir_dist_wheel))
sys.argv.append("--plat-name=%s" %(args.plat_name))
sys.argv.append("--python-tag=%s" %(python_tag))
sys.argv.append("egg_info")
sys.argv.append("--egg-base=%s" %(dir_egg_base))
setuptools.setup(
name = _name,
version = _version,
description = _desc,
packages = ['pykd'],
package_dir = {'pykd': os.path.relpath(dir_wheel_package)},
package_data = { 'pykd' :["*.pyd", "*.dll"]},
include_package_data=True,
zip_safe = False
) )
if 'bdist_zip' in unkonwn_args: elif "bdist_zip" in sys.argv:
zip_name = "pykd-%s-%s-%s.zip" %(_version, python_tag, args.plat_name)
print("Building bdist_zip %s ..." %(zip_name))
with zipfile.ZipFile(os.path.join(dir_dist_wheel, zip_name), mode='w') as archive:
print("zipped msdia140.dll")
archive.write(os.path.join(dir_solution, 'Obj', 'pykd', platform, "%s_%d.%d" %(configuration, sys.version_info.major, sys.version_info.minor), 'msdia140.dll'), arcname = 'msdia140.dll', compress_type = zipfile.ZIP_DEFLATED)
for dbgSdkBin in [ f for f in os.listdir(dir_dbgsdk_bin) if not os.path.isdir(f) ]:
print("zipped %s" %(dbgSdkBin))
archive.write(os.path.join(dir_dbgsdk_bin, dbgSdkBin), arcname = dbgSdkBin, compress_type = zipfile.ZIP_DEFLATED)
print("zipped pykd.pyd")
archive.write(os.path.join(dir_pykd_bin, 'pykd.pyd'), arcname = 'pykd.pyd', compress_type = zipfile.ZIP_DEFLATED)
print("zipped pykd.pdb")
archive.write(os.path.join(dir_pykd_bin, 'pykd.pdb'), arcname = 'pykd.pdb', compress_type = zipfile.ZIP_DEFLATED)
if __name__ == '__main__': #make package catalog
main()
if "--plat-name=win32" in sys.argv:
plat_name="win32"
elif "--plat-name=win-amd64" in sys.argv:
plat_name="win-amd64"
package_dir = os.path.join(os.path.curdir, _name )
if os.path.exists(package_dir):
shutil.rmtree(package_dir)
os.mkdir(package_dir)
bin_dir = os.path.join( os.path.curdir, '..', 'kdlibcpp/bin')
pykd_dir = os.path.join( os.path.curdir, '..', 'out')
if plat_name=="win32":
bin_dir = os.path.join( bin_dir, 'x86')
pykd_dir = os.path.join(pykd_dir, 'Win32', getReleaseSrc())
elif plat_name=="win-amd64":
bin_dir = os.path.join( bin_dir, 'x64')
pykd_dir = os.path.join(pykd_dir, 'X64', getReleaseSrc())
else:
assert(0)
pyver="%d%d" % sys.version_info[0:2]
zip_str = "pykd-%s-cp%s-%s" % ( _version, pyver, plat_name )
zip_name = zip_str + ".zip"
assert(os.path.isdir(bin_dir))
for binFile in [ f for f in os.listdir(bin_dir) if not os.path.isdir(f) ]:
shutil.copy( os.path.join(bin_dir, binFile), os.path.join(package_dir, binFile) )
shutil.copy( os.path.join(pykd_dir, 'pykd.pyd'), os.path.join(package_dir, 'pykd.pyd') )
dist_dir = os.path.join(os.path.curdir, 'dist')
if not os.path.exists(dist_dir):
os.mkdir(dist_dir)
with zipfile.ZipFile(os.path.join(os.path.curdir, 'dist', zip_name), mode='w' ) as archive:
for srcFile in os.listdir(package_dir):
print( "zipped %s" % (srcFile) )
archive.write( os.path.join(package_dir, srcFile), compress_type = zipfile.ZIP_DEFLATED)
print("OK")
elif "bdist_pdb" in sys.argv:
#make pdb archive
pyVersion = ('2.7', '3.5', '3.6', '3.7', '3.8', '3.9', '3.10', '3.11')
platform = ('Win32', 'x64')
pdbFiles = [ os.path.join( platform, 'Release_' + version, 'pykd.pdb') for version, platform in itertools.product( pyVersion, platform ) ]
zip_name = "pykd-%s-symbols.zip" % _version
with zipfile.ZipFile(os.path.join(os.path.curdir, 'dist', zip_name), mode='w' ) as archive:
for pdbFile in pdbFiles:
print( "zipped %s" % (pdbFile) )
archive.write( os.path.join(os.path.curdir, '..', 'out', pdbFile), pdbFile, compress_type = zipfile.ZIP_DEFLATED)
#pdbFileList = [ os.path.join( os.path.curdir, '..', 'out', fileName) for fileName in (
pass