liblzg: Binärpaket mit setup.py und ctype benutzung...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich hab keine Erfahrung mit ctypes und binären Erweiterung in Python... Ich möchte gern "liblzg" von Python aus nutzten.

liblzg Homepage -> http://liblzg.bitsnbites.eu/
liblzg Sourcecode -> https://github.com/mbitsnbites/liblzg

Es gibt https://github.com/stevenvergenz/python-lzg ... ist nicht viel code. Den möchte ich um eine "setup.py" erweitern und das ganze für Py2 und Py3 nutztbar machen.

Deswegen -> https://github.com/jedie/python-lzg

Die setup.py ist noch ganz übersichtlich:

Code: Alles auswählen

from distutils.core import setup, Extension

liblzg = Extension('liblzg',
                    include_dirs = ['liblzg/src/include'],
                    sources = [
                        'liblzg/src/lib/checksum.c',
                        'liblzg/src/lib/decode.c',
                        'liblzg/src/lib/encode.c',
                        'liblzg/src/lib/version.c',
                    ])

setup (
    name = 'python-lzg',
    version = '1.0',
    description = 'liblzg for python',
    ext_modules = [liblzg]
)
Beim installieren, wird auch die ".so" Datei erzeugt.
Sie landet in meinem Fall bei: /home/jens/pypyjs_env/lib/python3.4/site-packages/liblzg.cpython-34m.so

Doch das geht nicht:
ctypes.util.find_library('lzg') oder auch ctypes.util.find_library('liblzg')
beides liefert None, findet also die Datei nicht.

Mit dem Absoluten Pfad funktioniert es allerdings:
CLIB = ctypes.CDLL("/home/jens/pypyjs_env/lib/python3.4/site-packages/liblzg.cpython-34m.so")

Was mache ich falsch?!?


Als nächstes ist die Benutzung über ctypes "komisch"... Aber da hab ich keine Erfahrung. Komisch kommt mir vor, das man mit ctypes.create_string_buffer() arbeitet.
Kann man nicht direkt bytes hin und her schicken?!?


Könnt gern auch github fork/pull machen!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: bei mir wird jeweils nur ein liblzg.so ohne versionsspezifisches Postfix erzeugt. Diese Datei solltest Du ins Paketverzeichnis legen, da ctypes immer den vollen Dateinamen erwartet, kann man dann relativ zum Modul die Lib angeben.

Den Sinn einer Klasse erschließt sich mir nicht sofort. Auch würde ich als Rückgabewert Bytestrings bevorzugen. "create_string_buffer" ist einfach der einfachste Weg, einen Block Speicher zu bekommen.
Die Namensschreibweise entspricht nicht den Konventionen und dem Indexzugriff würde ich einen Attributzugriff vorziehen:

Code: Alles auswählen

import os
import ctypes

liblzg = ctypes.CDLL(os.path.join(os.path.dirname(__file__), 'liblzg.so'))

class Config(ctypes.Structure):
    _fields_ = [('level', ctypes.c_int32), ('fast', ctypes.c_int32)]


def compress(rawtext, level=5, fast=True):
    level = min(max(level, 1), 9)
    config = Config(level=level, fast=fast)

    # get the worst-case on encoded size
    max_enc_size = liblzg.LZG_MaxEncodedSize(len(rawtext))
    cout = ctypes.create_string_buffer(max_enc_size)

    enc_size = liblzg.LZG_Encode(rawtext, len(rawtext), cout, len(cout), ctypes.byref(config))
    return cout[:enc_size]


def decompress(data):
    est_dec_size = liblzg.LZG_DecodedSize(data, len(data))
    cout = ctypes.create_string_buffer(est_dec_size)
    dec_size = liblzg.LZG_Decode(data, len(data), cout, len(cout))
    return cout[:dec_size]
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Danke für deine Hilfe...

Die Frage ist, wie man setup.py anpassen kann,damit die .so Datei an einer bestimmten stelle liegt.
Bzw. Was ist hier best practise?

Du nutzt py2?

Die Klasse ist nicht von mir. Wahrscheinlich wären zwei Funktionen auf modulebene vollkommen ausreichend...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: das Verhalten ist für Python3 und 2 das selbe.
Pack einfach die Extension in das Packet:

Code: Alles auswählen

from distutils.core import setup, Extension

liblzg = Extension('lzg.liblzg',
                    include_dirs = ['liblzg/src/include'],
                    sources = [
                        'liblzg/src/lib/checksum.c',
                        'liblzg/src/lib/decode.c',
                        'liblzg/src/lib/encode.c',
                        'liblzg/src/lib/version.c',
                    ])

setup (
    name = 'python-lzg',
    version = '1.0',
    description = 'liblzg for python',
    packages = ['lzg'],
    ext_modules = [liblzg]
)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, das packages = ['lzg'], bringt es ;)

Dennoch landet unter Py3 die .so hier: env/lib/python3.4/site-packages/liblzg.cpython-34m.so
Und mit Py2 heißt sie: env/lib/python2.7/site-packages/liblzg.so

und es bleibt dabei, das alle folgenden Aufrufe None zurück liefern:

Code: Alles auswählen

print(ctypes.util.find_library('lzg'))
print(ctypes.util.find_library('liblzg'))
print(ctypes.util.find_library('lzg.liblzg'))

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: find_library sucht auch nur die üblichen Library-Pfade des Systems durch. Da aber Deine lib im Modul-Verzeichnis liegt, wird sie natürlich nicht gefunden. Daher der Weg über __file__. Man könnte es ja noch mit listdir kombinieren, wenn der lib-Name nicht eindeutig ist. Ich scheine da ein anderes distutils zu haben, weil bei meinem Python3 auch "liblzg.so" rauskommt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Aber irgendwie muß es dafür doch eine einfach Lösung geben. Hat doch eigentlich jeder das Problem, wenn er ctype benutzt, oder?

__file__ zu nutzten, ist auch nicht so einfach, wenn es, wie bei mir im env, unter src das selbe Modul gibt.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: die Lib kann entweder global im System installiert sein, dann kannst Du find_library benutzen, oder sie liegt lokal beim Modul, dann ist __file__ doch eindeutig die Datei, die Du auch importiert hast. Das Modul unter "src" solltest Du doch eigentlich nie importieren, sondern immer nur unter "build".
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Könnte mir wahrscheinlich abgucken wie es https://github.com/wnyc/py-zopfli/blob/master/setup.py macht.

Wobei das wahrscheinlich nur Py2 ist.

Aber LZG kommt wohl eh nicht in Frage, von daher verfolge ich das erstmal nicht weiter...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten