Länka in statiskt lib i python

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
El-Björn
Inlägg: 89
Blev medlem: 16 januari 2005, 02:28:16
Ort: Kungälv

Länka in statiskt lib i python

Inlägg av El-Björn »

Jag försöker använda en BME680 för att mäta luftkvalite genom att koppla densamma till en Raspberry Pi och skriva kod i Python.

Sensor-kortet är gjort av Pimoroni och har ett mjukvarupaket för att få igång sensorn. Därigenom får man ut rådata från sensorn i form av temperatur, tryck, luftfuktighet och en resistans som är beroende på mängden flyktiga organiska sammansättningar (VOC) i luften.
Dock om man läser på om sensorn hos tillverkaren Bosch så är den grovkalibrerad och har dessutom funktioner som räknar ut ett luftkvalite-index med hjälp av en algoritm som inte är angiven i klartext utan kan laddas ner i form av ett statiskt lib från hemsidan.

Där kommer mitt problem för stunden: jag får inte inlänkandet av biblioteket i python att fungera.

Med biblioteket medföljer två header-filer och jag har lagt allt i en lib-katalog där då dessa filer ligger:
bsec_datatypes.h
bsec_interface.h
libalgobsec.a

Jag skapar sedan desssa två filer:
bsec.pyx
setup.py

Där bsec.pyx innehåller detta:

Kod: Markera allt

cdef extern from "bsec_interface.h":
        bsec_library_return_t bsec_init()

def bsec_init():
        bsec_init()
Och setup.py:

Kod: Markera allt

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

bsec_interface_extension = Extension(
        name="bsec_interface",
        sources=["bsec.pyx"],
        libraries=["algobsec"],
        library_dirs=["lib"],
        include_dirs=["lib"]
)

setup(
        name="bsec_interface",
        ext_modules=cythonize([bsec_interface_extension])
)
Jag bygger detta med kommandot

Kod: Markera allt

python3 setup.py build_ext --inplace
Och det kompilerar med detta resultat:

Kod: Markera allt

pi@raspberrypi:~/python/bme680 $ python3 setup.py build_ext --inplace
Compiling bsec.pyx because it changed.
[1/1] Cythonizing bsec.pyx
/home/pi/.local/lib/python3.5/site-packages/Cython/Compiler/Main.py:367: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /home/pi/python/bme680/bsec.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)
warning: bsec.pyx:8:0: Overriding cdef method with def method.
running build_ext
building 'bsec_interface' extension
creating build
creating build/temp.linux-armv7l-3.5
arm-linux-gnueabihf-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fdebug-prefix-map=/build/python3.5-6waWnr/python3.5-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -Ilib -I/usr/include/python3.5m -c bsec.c -o build/temp.linux-armv7l-3.5/bsec.o
arm-linux-gnueabihf-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,relro -g -fdebug-prefix-map=/build/python3.5-6waWnr/python3.5-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-armv7l-3.5/bsec.o -Llib -lalgobsec -o /home/pi/python/bme680/bsec_interface.cpython-35m-arm-linux-gnueabihf.so
Ser ju bra ut, inga felmeddelanden i alla fall. Start python3 och importerar och kör den funktionen som jag tagit in, nämligen bsec_init():

Kod: Markera allt

Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import bsec_interface as bsec
>>> bsec.bsec_init()
Traceback (most recent call last):
  File "bsec.pyx", line 9, in bsec_interface.bsec_init
    bsec_init()
  File "bsec.pyx", line 9, in bsec_interface.bsec_init
    bsec_init()
	.
	[Massa rader med samma innehåll bortklippta här]
	.
  File "bsec.pyx", line 9, in bsec_interface.bsec_init
    bsec_init()
RecursionError: maximum recursion depth exceeded while calling a Python object
Okej... Så bsec_init() verkar anropa bsec_init() i oändlighet.
Testar att byta namn på funktionen i bsec.pyx till py_bsec_init() men får då följande felmeddelande:

Kod: Markera allt

omlokalisering R_ARM_MOVW_ABS_NC mot ”a local symbol” kan inte användas när ett delat objekt skapas; kompilera om med -fPIC
Är det någon som ser vad det är som är tokigt?
Man ska även plocka in fler filer från ett API som finns att ladda ner, men jag tänkte börja med att länka in biblioteket för att se hur långt jag kommer.
Sado
Inlägg: 84
Blev medlem: 6 april 2007, 14:39:33
Ort: Svealand

Re: Länka in statiskt lib i python

Inlägg av Sado »

Ja, bsec_init() anropar väl sig själv istället för den externa funktionen så omdöpning må vara det korrekta här. Det andra felet då. Har du provat att "Kompilera om med -fPIC" om det säger dig något?
Användarvisningsbild
El-Björn
Inlägg: 89
Blev medlem: 16 januari 2005, 02:28:16
Ort: Kungälv

Re: Länka in statiskt lib i python

Inlägg av El-Björn »

Jag kan tyvärr inte kompilera om koden utan har bara ett färdig-kompilerat statiskt bibliotek (libalgobsec.a).
Bo.Siltberg
Inlägg: 357
Blev medlem: 30 juli 2018, 06:46:13

Re: Länka in statiskt lib i python

Inlägg av Bo.Siltberg »

Jag vet inte, men spontant skulle jag vilja försöka hitta ett bra modulnamn att stoppa in i anropet, t.ex algobsec, bsec_interface eller nåt.

Kod: Markera allt

def bsec_init():
        algobsec.bsec_init()
mounte
Inlägg: 204
Blev medlem: 14 november 2010, 13:15:00
Ort: Sandviken

Re: Länka in statiskt lib i python

Inlägg av mounte »

Vet inte om följande hjälper dig fullt ut men det är fungerande exempel (C) för att använda libbet
https://github.com/alexh-name/bsec_bme680_linux

En workaround om du inte lyckas kompilera det hela är att använda något i stil med
https://github.com/timothybrown/BSEC-Conduit
dvs, ha en annan process som bara hanterar sensorn och publicerar mqtt eller något annat. Från python kan du sedan lyssna på den strömmen av data.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Länka in statiskt lib i python

Inlägg av johano »

Nu kanske du redan kommit vidare, men i Cython-doc beskrivs hur man kan undvika namnkonflikter:

https://cython.readthedocs.io/en/latest ... ifications
Användarvisningsbild
El-Björn
Inlägg: 89
Blev medlem: 16 januari 2005, 02:28:16
Ort: Kungälv

Re: Länka in statiskt lib i python

Inlägg av El-Björn »

@Bo.Siltberg och @johano

Tack! Era svar visade på att jag inte var helt ute och cyklade, för jag lade in kod i en fil döpt till cbsec.pxd som jag sedan försökte med denna kodsnutten: (jag skriver ur minnet nu då prylarna ligger hemma och jag är på fiskesemester i härliga Härjedalen)

Kod: Markera allt

cimport cbsec.pxd

def bsec_init():
        cbsec.bsec_init()
@mounte:
Grymt! Det är precis vad jag vill uppnå. Att någon hade skrivit ett fullt fungerande paket för att hantera bsec lyckades mina google-sökningar missa... Jag var så inriktad på att få in biblioteket i python så jag missade grundspåret.

Jag kom en bit innan jag åkte iväg men fick lite problem med att installera paho mqtt c, vilket såklart åt upp en hel del tid innan jag förstod vari problemet låg. Jag får rapportera lite bättre när jag sitter med prylarna igen.
Användarvisningsbild
El-Björn
Inlägg: 89
Blev medlem: 16 januari 2005, 02:28:16
Ort: Kungälv

Re: Länka in statiskt lib i python

Inlägg av El-Björn »

Så hur gick det här till slut? Jodå, tack vare tipsen i denna tråden fick jag till slut ihop allt. Nu sitter det fyra raspberry pi utplacerade i lokalerna och levererar data till en server.
Tack vare tipset om c-programmet som är skrivet så kompletterade jag detta med funktioner för MQTT, vilket i princip saxades ur paho mqtt-exempel. Så nu levereras data denna vägen:

raspi+bme680 [mqtt publish] → maqiatto.com → [mqtt subscribe] telegraf → influxdb → grafana

PAHO MQTT är ett paket för att hantera MQTT i diverse olika programmeringsspråk.
MaQiaTTo är en gratis mqtt-broker.
Telegraf och influxdb är två tjänster som jag upplevde simpla att installera och konfigurera. Influxdb är en databas byggd för att hantera tidsstämplad data och Telegraf är en tjänst som går att, bland annat, sätta upp för att prenumerera på MQTT-ämnen.
Grafana var bara att hänga på influxdb och sätta upp graferna. Ett exempel på graf:
grafana.jpg
Anledningen till att jag använde MaQiaTTo som mellanled är att servern står inte i samma nät som sensorerna.

Något som stoppade mig länge var att jag inte förstod vad gcc-flaggan -static gjorde. Denna var satt i det github-projektet jag använde, och då vägrade den länka in mqtt-paketet. Vilket inte var så konstigt då mqtt-paketet är dynamiskt och -static enbart tillåter statisk inlänkning och jag förstod det hela rätt. Tog jag bort den så löste det sig i alla fall.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
tingo
Inlägg: 285
Blev medlem: 17 maj 2017, 17:55:40
Ort: Oslo, Norge

Re: Länka in statiskt lib i python

Inlägg av tingo »

Nice! Om du får trøbbel med at Telegraf slutter å ta i mot data, sjekk loggen, det kan være at den mister mqtt-tilkobling. Enkleste er da å restarte Telegraf.
Användarvisningsbild
El-Björn
Inlägg: 89
Blev medlem: 16 januari 2005, 02:28:16
Ort: Kungälv

Re: Länka in statiskt lib i python

Inlägg av El-Björn »

Tack för tipset! :tumupp:
Skriv svar