Skip to content

Commit 4c2789d

Browse files
authored
Merge pull request #1 from lynnporu/dev
Implement library
2 parents db7dfd6 + 0f39b36 commit 4c2789d

File tree

6 files changed

+635
-0
lines changed

6 files changed

+635
-0
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<p align="center">
2+
<img src="https://github.com/lynnporu/annotatec/raw/dev/logo.png">
3+
</p>
4+
5+
![PyPI](https://img.shields.io/pypi/v/annotatec)
6+
![GitHub repo size](https://img.shields.io/github/repo-size/lynnporu/annotatec)
7+
![GitHub](https://img.shields.io/github/license/lynnporu/annotatec)
8+
9+
------------
10+
11+
**annotatec** helps you create Python packages with C embeddings.
12+
13+
Imagine you're developing C library and already have more than 50 functions. Sometimes you change signatures of old functions or rename them. It'll be headache to write and support all [ctypes](https://docs.python.org/3/library/ctypes.html)-declarations for Python wrapper. **annotatec** will create all Python objects for you. All you need is to provide declarations, which can be placed directly into your C code.
14+
15+
## Minimal livable example
16+
17+
You have some library `lib.c` and it's header `lib.h`. These files were compiled into `lib.so` (or `lib.dll` in Windows).
18+
19+
`lib.c` source:
20+
```c
21+
#include "lib.h"
22+
int sum(int a, short b, long long c) { return a + b + c; }
23+
```
24+
25+
`lib.h` source:
26+
```c
27+
/* @function sum
28+
* @return int
29+
* @argument int
30+
* @argument short
31+
* @argument longlong
32+
*/
33+
int sum(int, short, long long);
34+
```
35+
36+
Here's a Python wrapper:
37+
```python
38+
import annotatec
39+
40+
libc = annotatec.Loader(
41+
library="lib.so", headers=["lib.h"])
42+
```
43+
44+
That's all! Now you can test it like so:
45+
```python
46+
>>> libc.sum(1, 2, 3)
47+
<<< 6
48+
```
49+
## Reference
50+
51+
Read detailed reference in [wiki](https://github.com/lynnporu/annotatec/wiki)-pages.

annotatec/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .parser import *
2+
from .loader import *

annotatec/loader.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import ctypes
2+
import typing
3+
4+
from . import parser
5+
6+
7+
class Loader:
8+
"""Base class for loading and parsing libraries.
9+
"""
10+
11+
def __init__(
12+
self,
13+
library: typing.Union[str, ctypes.CDLL],
14+
headers: typing.List[typing.Union[str, typing.TextIO]],
15+
precompile: bool = True
16+
):
17+
"""Loads library and parse headers.
18+
19+
Arguments:
20+
library: str or ctypes.CDLL - address of the shared objects (DLL)
21+
or opened library.
22+
headers: list of strings or list of files - files with declarations
23+
to parse.
24+
precompile: bool - if set to True, than all objects will be
25+
compiled immediately. This option allows to lazy compile
26+
only objects that are needed.
27+
28+
"""
29+
30+
self.libc = (
31+
ctypes.cdll.LoadLibrary(library)
32+
if isinstance(library, str)
33+
else library)
34+
self.parser = parser.FileParser(lib=self.libc)
35+
36+
if precompile:
37+
self.parser.parse_files(headers)
38+
else:
39+
self.parser.scrap_files(headers)
40+
41+
def __getattr__(self, key):
42+
return self.parser.declarations.compile(key)

0 commit comments

Comments
 (0)