C++ dll-bol char** Python-ba

Udv,

Van egy C++-ban irt .dll aminek a fuggvenyeit Python-bol kellene meghivnom. Hogyan tudnam Python-bol hasznalni a kovetkezo szignaturaju fuggvenyt?:

int func (char **);

Az alabbi mukodik, de itt ugye csak char * es nem char ** van:

GetDeviceName = Debug.GetDeviceName
Debug_GetDeviceName.restype = c_int
Debug_GetDeviceName.argtypes = [c_char_p]

status = SiDebug_GetDeviceName(name)

Koszi,

/sza2

Hozzászólások

Írj a Python és a DLL közé egy wrappert.

Fuszenecker_Róbert

Ez egy kicsit bovebben jobb lenne:-)

Ugy erted, C/C++ ban? - Akkor ugy erzem, vegig kellene vezetnem a tobb tiz fuggvenyt a wrapper-en.

Nincs erre valami altalanosan elfogadott megoldas? Vegulis ez egy 2 dimenzios tomb, jelen esetben 0-val vegzodo karakterlancok tombje, kb. mint 'argv'.

Nem tudom ezt valahogy egyszeruen kinyerni Python-ban?

/sza2

Pythonból még nem hívtam bele DLL-be (C#-ból viszont szoktam), szóval kicsit általános lesz a hozzászólásom.

Írj egy DLL-t, amiből helyesen meg tudod hívni az eredeti DLL függvényeit (és persze teszteld is le), de úgy, hogy a köztes DLL függvényeit könnyen meg tudd hívni Pythonból. A fekete mágia részét (pointer -> pointerre mutató pointer) pedig a köztes (wrapper) DLL-ben oldd meg.

Műszaki ember rajzból ért:
Python -> Wrapper -> eredeti DLL

Jobb megoldás most nem jut eszembe.
Viszont ha sikerül, oszd meg velünk is, mert a hasonló topikikat megtalálja a Google is :-) Hátha valamikor másnál is előkerül ugyanez a dolog.

Fuszenecker_Róbert

Használj swig-et, ha nem csak egy-két függvényről van szó.

Alapvetően két lehetőséged van:
Az első amivel ha jól látom most próbálkozol, a ctypes-os megoldás. Most hirtelen elolvasva a dokumentációt én sem látom, hogy tudnád megoldani ezzel.

A második lehetőség valamilyen wrapper írása.
Ezen belül viszont megint két lehetőséged van:
1) Írsz egy ctype barát wrappert C-ben és küzdesz azzal
2) Írsz egy rendes Python modult.

Az első egy kicsit csúnya, és nem biztos hogy gyors megoldáshoz vezet.

A 2) esetében megint egy rakás választásod van:
a) Megírod a wrapper modult C-ben ahogy írva vagyon itt.
b) Megírod a wrapper modult C++-ban ahogy írva vagyon itt. (Boost python)
c) Generálod a wrappert ahogy írva vagyon itt. (SWIG)
d) Megírod a wrapper modult python+C-ben ahogy írva vagyon itt. (Cython/Pyrex)

Az a) nekem macerásnak tűnik, ha nem csináltál még ilyet.
A b) igen egyszerű és gyors megoldás, ha van C++ gyakorlatod és a Boost kéznél van. (Egyéb esetben nem ajánlom, hogy belekezdj.)
A c)-ről nincs személyes tapasztalatom, de egyrészt ágyúval verébre, másrészt nem az egyszerűségéről híres
A d)-vel van tapasztalatom, bár nem erre használtam, csak optimalizációra. Arra nagyon kényelmes volt, gyanítom ez sem okozhat vele problémát.

Én személy szerint a b) és d) közül választanék attól függően, hogy mennyire komplex wrappert akarok használni.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Swig-et használva mondjuk nagy az esélye, hogy nem kell C/C++-ban programozni, csak a swig-et kell megismerni kicsit. Mint utaltam rá korábban, 1-2 funkciónál nem jön elő az előnye, de kicsit több funkció, osztály, stb. használata esetén már komoly időmegtakarítás, kevesebb hibalehetőség, jobb karbantarthatóság, stb.
Az egyszerűséggel kapcsolatban nem tudom mi a gond, a többi általad felsorolt megoldás is legalább hasonló bonyolultságú, mint a swig-es, sőt...

"Swig-et használva mondjuk nagy az esélye, hogy nem kell C/C++-ban programozni, csak a swig-et kell megismerni kicsit."

És ez pont a legnagyobb hátránya, mivel ha valaki python-ból hívogat C fv-eket, akkor feltételezhetjük, hogy két dolgot ismer valamennyire: a pythont és a C-t. :)

De még ha ez nem is igaz, az tény, hogy egy olyan új "nyelvet" kell megtanulni amit egyébként nem használ az ember másra.
Ez mondjuk igaz a cython-ra is, bár szerintem egy python fejlesztőnek az elég hasznos tud lenni.

A bonyolultságról meg annyit, hogy a swig-es tutorial alapján gyakorlatilag esélytelen a fentebb vázolt string tömbös fv használata, sőt ez alapján még azt is megkockáztatom, hogy lehetetlen. (Ugyan sza2king nem fogalmaz egyértelműen, de nekem a char** parameter output paraméternek tőnik...)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

"Reménykedtem", hogy nem a kérdező az első ember a földön, aki ilyesmit akar megoldani swiggel... ;)
1 perc swig doksiban keresgélés után a a megoldás: Converting Python list to a char **

Copy paste, és egy parancs futtatása után kész a wrapper - ennél egyszerűbb nem tudom mi tud lenni, hozzá se kell szagolni a C részhez.

Az új nyelv az kb. 5 darab direktíva.

De nem hit térítek tovább.

Ez momentán semmivel nem egyszerűbb mint bármelyik másik, és konkrétan a python C API-t használja, szóval nem igaz, hogy nem kell a C-hez hozzászagolni.
Persze nyilván egyszerű lenne a copy-paste, de az én értelmezésem szerint a fordított irány kell a kedves kérdezőnek (char** -> Python list).

Mondjuk nem úgy néz ki mint akit érdekelnek a válaszok, szóval részemről én is befejeztem. :)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Subs, annak idején ezért hagytam ott a PyQt4-et.