12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139 |
- \input texinfo @c -*- Mode: Texinfo; Mode: auto-fill -*-
- @c %**start of header
- @setfilename cffi.info
- @settitle CFFI User Manual
- @exampleindent 2
- @c @documentencoding utf-8
- @c Style notes:
- @c
- @c * The reference section names and "See Also" list are roman, not
- @c @code. This is to follow the format of CLHS.
- @c
- @c * How it looks in HTML is the priority.
- @c ============================= Macros =============================
- @c The following macros are used throughout this manual.
- @macro Function {args}
- @defun \args\
- @end defun
- @end macro
- @macro Macro {args}
- @defmac \args\
- @end defmac
- @end macro
- @macro Accessor {args}
- @deffn {Accessor} \args\
- @end deffn
- @end macro
- @macro GenericFunction {args}
- @deffn {Generic Function} \args\
- @end deffn
- @end macro
- @macro ForeignType {args}
- @deftp {Foreign Type} \args\
- @end deftp
- @end macro
- @macro Variable {args}
- @defvr {Special Variable} \args\
- @end defvr
- @end macro
- @macro Condition {args}
- @deftp {Condition Type} \args\
- @end deftp
- @end macro
- @macro cffi
- @acronym{CFFI}
- @end macro
- @macro impnote {text}
- @quotation
- @strong{Implementor's note:} @emph{\text\}
- @end quotation
- @end macro
- @c Info "requires" that x-refs end in a period or comma, or ) in the
- @c case of @pxref. So the following implements that requirement for
- @c the "See also" subheadings that permeate this manual, but only in
- @c Info mode.
- @ifinfo
- @macro seealso {name}
- @ref{\name\}.
- @end macro
- @end ifinfo
- @ifnotinfo
- @alias seealso = ref
- @end ifnotinfo
- @c Typeset comments in roman font for the TeX output.
- @iftex
- @alias lispcmt = r
- @end iftex
- @ifnottex
- @alias lispcmt = asis
- @end ifnottex
- @alias res = result
- @c ============================= Macros =============================
- @c Show types, functions, and concepts in the same index.
- @syncodeindex tp cp
- @syncodeindex fn cp
- @copying
- Copyright @copyright{} 2005 James Bielman <jamesjb at jamesjb.com> @*
- Copyright @copyright{} 2005-2015 Lu@'{@dotless{i}}s Oliveira
- <loliveira at common-lisp.net> @*
- Copyright @copyright{} 2005-2006 Dan Knapp <danka at accela.net> @*
- Copyright @copyright{} 2005-2006 Emily Backes <lucca at accela.net> @*
- Copyright @copyright{} 2006 Stephen Compall <s11 at member.fsf.org>
- @quotation
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- @sc{The software is provided ``as is'', without warranty of any kind,
- express or implied, including but not limited to the warranties of
- merchantability, fitness for a particular purpose and noninfringement.
- In no event shall the authors or copyright holders be liable for any
- claim, damages or other liability, whether in an action of contract,
- tort or otherwise, arising from, out of or in connection with the
- software or the use or other dealings in the software.}
- @end quotation
- @end copying
- @c %**end of header
- @dircategory Software development
- @direntry
- * CFFI Manual: (cffi-manual). CFFI Manual.
- @end direntry
- @titlepage
- @title CFFI User Manual
- @c @subtitle Version X.X
- @c @author James Bielman
- @page
- @vskip 0pt plus 1filll
- @insertcopying
- @end titlepage
- @contents
- @ifnottex
- @node Top, Introduction, (dir), (dir)
- @top cffi
- @insertcopying
- @end ifnottex
- @menu
- * Introduction:: What is CFFI?
- * Installation::
- * Implementation Support::
- * Tutorial:: Interactive intro to using CFFI.
- * Wrapper generators:: CFFI forms from munging C source code.
- * Foreign Types::
- * Pointers::
- * Strings::
- * Variables::
- * Functions::
- * Libraries::
- * Callbacks::
- * The Groveller::
- * Static Linking::
- * Limitations::
- * Platform-specific features:: Details about the underlying system.
- * Glossary:: List of CFFI-specific terms and meanings.
- * Comprehensive Index::
- @detailmenu
- --- Dictionary ---
- Foreign Types
- * convert-from-foreign:: Outside interface to backward type translator.
- * convert-to-foreign:: Outside interface to forward type translator.
- * defbitfield:: Defines a bitfield.
- * defcstruct:: Defines a C structure type.
- * defcunion:: Defines a C union type.
- * defctype:: Defines a foreign typedef.
- * defcenum:: Defines a C enumeration.
- * define-foreign-type:: Defines a foreign type specifier.
- * define-parse-method:: Specifies how a type should be parsed.
- @c * explain-foreign-slot-value:: <unimplemented>
- * foreign-bitfield-symbols:: Returns a list of symbols for a bitfield type.
- * foreign-bitfield-value:: Calculates a value for a bitfield type.
- * foreign-enum-keyword:: Finds a keyword in an enum type.
- * foreign-enum-value:: Finds a value in an enum type.
- * foreign-slot-names:: Returns a list of slot names in a foreign struct.
- * foreign-slot-offset:: Returns the offset of a slot in a foreign struct.
- * foreign-slot-pointer:: Returns a pointer to a slot in a foreign struct.
- * foreign-slot-value:: Returns the value of a slot in a foreign struct.
- * foreign-type-alignment:: Returns the alignment of a foreign type.
- * foreign-type-size:: Returns the size of a foreign type.
- * free-converted-object:: Outside interface to typed object deallocators.
- * free-translated-object:: Defines how to free a oreign object.
- * translate-from-foreign:: Defines a foreign-to-Lisp object translation.
- * translate-to-foreign:: Defines a Lisp-to-foreign object translation.
- * with-foreign-object:: Allocates a foreign object with dynamic extent.
- * with-foreign-objects:: Plural form of @code{with-foreign-object}.
- * with-foreign-slots:: Accesses the slots of a foreign structure.
- Pointers
- * foreign-free:: Deallocates memory.
- * foreign-alloc:: Allocates memory.
- * foreign-symbol-pointer:: Returns a pointer to a foreign symbol.
- * inc-pointer:: Increments the address held by a pointer.
- * incf-pointer:: Increments the pointer address in a place.
- * make-pointer:: Returns a pointer to a given address.
- * mem-aptr:: The pointer to an element of an array.
- * mem-aref:: Accesses the value of an index in an array.
- * mem-ref:: Dereferences a pointer.
- * null-pointer:: Returns a NULL pointer.
- * null-pointer-p:: Tests a pointer for NULL value.
- * pointerp:: Tests whether an object is a pointer or not.
- * pointer-address:: Returns the address pointed to by a pointer.
- * pointer-eq:: Tests if two pointers point to the same address.
- * with-foreign-pointer:: Allocates memory with dynamic extent.
- Strings
- * *default-foreign-encoding*:: Default encoding for the string types.
- * foreign-string-alloc:: Converts a Lisp string to a foreign string.
- * foreign-string-free:: Deallocates memory used by a foreign string.
- * foreign-string-to-lisp:: Converts a foreign string to a Lisp string.
- * lisp-string-to-foreign:: Copies a Lisp string into a foreign string.
- * with-foreign-string:: Allocates a foreign string with dynamic extent.
- * with-foreign-strings:: Plural form of @code{with-foreign-string}.
- * with-foreign-pointer-as-string:: Similar to CL's with-output-to-string.
- Variables
- * defcvar:: Defines a C global variable.
- * get-var-pointer:: Returns a pointer to a defined global variable.
- Functions
- * defcfun:: Defines a foreign function.
- * foreign-funcall:: Performs a call to a foreign function.
- * foreign-funcall-pointer:: Performs a call through a foreign pointer.
- * translate-camelcase-name:: Converts a camelCase foreign name to/from a Lisp name.
- * translate-name-from-foreign:: Converts a foreign name to a Lisp name.
- * translate-name-to-foreign:: Converts a Lisp name to a foreign name.
- * translate-underscore-separated-name:: Converts an underscore_separated foreign name to/from a Lisp name.
- Libraries
- * close-foreign-library:: Closes a foreign library.
- * *darwin-framework-directories*:: Search path for Darwin frameworks.
- * define-foreign-library:: Explain how to load a foreign library.
- * *foreign-library-directories*:: Search path for shared libraries.
- * load-foreign-library:: Load a foreign library.
- * load-foreign-library-error:: Signalled on failure of its namesake.
- @c * reload-foreign-libraries:: Reload foreign libraries.
- * use-foreign-library:: Load a foreign library when needed.
- Callbacks
- * callback:: Returns a pointer to a defined callback.
- * defcallback:: Defines a Lisp callback.
- * get-callback:: Returns a pointer to a defined callback.
- @end detailmenu
- @end menu
- @c ===================================================================
- @c CHAPTER: Introduction
- @node Introduction, Installation, Top, Top
- @chapter Introduction
- @cffi{} is the Common Foreign Function Interface for @acronym{ANSI}
- Common Lisp systems. By @dfn{foreign function} we mean a function
- written in another programming language and having different data and
- calling conventions than Common Lisp, namely, C. @cffi{} allows you
- to call foreign functions and access foreign variables, all without
- leaving the Lisp image.
- We consider this manual ever a work in progress. If you have
- difficulty with anything @cffi{}-specific presented in the manual,
- please contact @email{cffi-devel@@common-lisp.net,the developers} with
- details.
- @heading Motivation
- @xref{Tutorial-Comparison,, What makes Lisp different}, for
- an argument in favor of @acronym{FFI} in general.
- @cffi{}'s primary role in any image is to mediate between Lisp
- developers and the widely varying @acronym{FFI}s present in the
- various Lisp implementations it supports. With @cffi{}, you can
- define foreign function interfaces while still maintaining portability
- between implementations. It is not the first Common Lisp package with
- this objective; however, it is meant to be a more malleable framework
- than similar packages.
- @heading Design Philosophy
- @itemize
- @item
- Pointers do not carry around type information. Instead, type
- information is supplied when pointers are dereferenced.
- @item
- A type safe pointer interface can be developed on top of an
- untyped one. It is difficult to do the opposite.
- @item
- Functions are better than macros. When a macro could be used
- for performance, use a compiler-macro instead.
- @end itemize
- @c ===================================================================
- @c CHAPTER: Installation
- @node Installation, Implementation Support, Introduction, Top
- @chapter Installation
- @cffi{} can be obtained through one of the following means available
- through its @uref{http://common-lisp.net/project/cffi/,,website}:
- @itemize
- @item
- @uref{http://common-lisp.net/project/cffi/releases/?M=D,,official release
- tarballs}
- @item
- @uref{http://common-lisp.net/gitweb?p=projects/cffi/cffi.git,,git
- repository}
- @c snapshots have been disabled as of
- @c @item
- @c @uref{http://common-lisp.net/project/cffi/tarballs/?M=D,,nightly-generated
- @c snapshots}
- @end itemize
- In addition, you will need to obtain and install the following
- dependencies:
- @itemize
- @item
- @uref{http://common-lisp.net/project/babel/,,Babel}, a charset
- encoding/decoding library.
- @item
- @uref{http://common-lisp.net/project/alexandria/,,Alexandria}, a
- collection of portable public-domain utilities.
- @item
- @uref{http://www.cliki.net/trivial-features,,trivial-features}, a
- portability layer that ensures consistent @code{*features*} across
- multiple Common Lisp implementations.
- @end itemize
- Furthermore, if you wish to run the testsuite,
- @uref{http://www.cliki.net/rt,,RT} is required.
- You may find mechanisms such as
- @uref{https://www.quicklisp.org/beta/,Quicklisp} (recommended)
- or @uref{http://common-lisp.net/project/clbuild/,,clbuild} (for advanced
- uses) helpful in getting and managing @cffi{} and its
- dependencies.
- @c ===================================================================
- @c CHAPTER: Implementation Support
- @node Implementation Support, Tutorial, Installation, Top
- @chapter Implementation Support
- @cffi{} supports various free and commercial Lisp implementations:
- @acronym{ABCL}, Allegro CL, Clasp, @sc{clisp}, Clozure CL,
- @acronym{CMUCL}, Corman CL, @acronym{ECL}, @acronym{GCL}, LispWorks,
- @acronym{MCL}, @acronym{SBCL} and the Scieneer CL.
- In general, you should work with the latest versions of each
- implementation since those will usually be tested against recent
- versions of CFFI more often and might include necessary features or
- bug fixes. Reasonable patches for compatibility with earlier versions
- are welcome nevertheless.
- @section Limitations
- Some features are not supported in all implementations.
- @c TODO: describe these features here.
- @c flat-namespace too
- @subheading Allegro CL
- @itemize
- @item
- Does not support the @code{:long-long} type natively.
- @item
- Unicode support is limited to the Basic Multilingual Plane (16-bit
- code points).
- @end itemize
- @subheading Clasp
- @itemize
- @item
- Only supports a flat namespace.
- @end itemize
- @subheading CMUCL
- @itemize
- @item
- No Unicode support. (8-bit code points)
- @end itemize
- @subheading Corman CL
- @itemize
- @item
- Does not support @code{foreign-funcall}.
- @end itemize
- @subheading @acronym{ECL}
- @itemize
- @item
- On platforms where ECL's dynamic FFI is not supported (ie. when
- @code{:dffi} is not present in @code{*features*}),
- @code{cffi:load-foreign-library} does not work and you must use ECL's
- own @code{ffi:load-foreign-library} with a constant string argument.
- @end itemize
- @subheading Lispworks
- @itemize
- @item
- Does not completely support the @code{:long-long} type natively in
- 32-bit platforms.
- @item
- Unicode support is limited to the Basic Multilingual Plane (16-bit
- code points).
- @end itemize
- @subheading @acronym{SBCL}
- @itemize
- @item
- Not all platforms support callbacks.
- @end itemize
- @c ===================================================================
- @c CHAPTER: An Introduction to Foreign Interfaces and CFFI
- @c This macro is merely a marker that I don't think I'll use after
- @c all.
- @macro tutorialsource {text}
- @c \text\
- @end macro
- @c because I don't want to type this over and over
- @macro clikicffi
- http://www.cliki.net/CFFI
- @end macro
- @c TeX puts spurious newlines in when you use the above macro
- @c in @examples &c. So it is expanded below in some places.
- @node Tutorial, Wrapper generators, Implementation Support, Top
- @chapter An Introduction to Foreign Interfaces and @acronym{CFFI}
- @c Above, I don't use the cffi macro because it breaks TeX.
- @cindex tutorial, @cffi{}
- Users of many popular languages bearing semantic similarity to Lisp,
- such as Perl and Python, are accustomed to having access to popular C
- libraries, such as @acronym{GTK}, by way of ``bindings''. In Lisp, we
- do something similar, but take a fundamentally different approach.
- This tutorial first explains this difference, then explains how you
- can use @cffi{}, a powerful system for calling out to C and C++ and
- access C data from many Common Lisp implementations.
- @cindex foreign functions and data
- The concept can be generalized to other languages; at the time of
- writing, only @cffi{}'s C support is fairly complete. Therefore, we
- will interchangeably refer to @dfn{foreign functions} and @dfn{foreign
- data}, and ``C functions'' and ``C data''. At no time will the word
- ``foreign'' carry its usual, non-programming meaning.
- This tutorial expects you to have a working understanding of both
- Common Lisp and C, including the Common Lisp macro system.
- @menu
- * Tutorial-Comparison:: Why FFI?
- * Tutorial-Getting a URL:: An FFI use case.
- * Tutorial-Loading:: Load libcurl.so.
- * Tutorial-Initializing:: Call a function in libcurl.so.
- * Tutorial-easy_setopt:: An advanced libcurl function.
- * Tutorial-Abstraction:: Why breaking it is necessary.
- * Tutorial-Lisp easy_setopt:: Semi-Lispy option interface.
- * Tutorial-Memory:: In C, you collect the garbage.
- * Tutorial-Callbacks:: Make useful C function pointers.
- * Tutorial-Completion:: Minimal get-url functionality.
- * Tutorial-Types:: Defining new foreign types.
- * Tutorial-Conclusion:: What's next?
- @end menu
- @node Tutorial-Comparison, Tutorial-Getting a URL, Tutorial, Tutorial
- @section What makes Lisp different
- The following sums up how bindings to foreign libraries are usually
- implemented in other languages, then in Common Lisp:
- @table @asis
- @item Perl, Python, Java, other one-implementation languages
- @cindex @acronym{SWIG}
- @cindex Perl
- @cindex Python
- Bindings are implemented as shared objects written in C. In some
- cases, the C code is generated by a tool, such as @acronym{SWIG}, but
- the result is the same: a new C library that manually translates
- between the language implementation's objects, such as @code{PyObject}
- in Python, and whatever C object is called for, often using C
- functions provided by the implementation. It also translates between
- the calling conventions of the language and C.
- @item Common Lisp
- @cindex @acronym{SLIME}
- Bindings are written in Lisp. They can be created at-will by Lisp
- programs. Lisp programmers can write new bindings and add them to the
- image, using a listener such as @acronym{SLIME}, as easily as with
- regular Lisp definitions. The only foreign library to load is the one
- being wrapped---the one with the pure C interface; no C or other
- non-Lisp compilation is required.
- @end table
- @cindex advantages of @acronym{FFI}
- @cindex benefits of @acronym{FFI}
- We believe the advantages of the Common Lisp approach far outweigh any
- disadvantages. Incremental development with a listener can be as
- productive for C binding development as it is with other Lisp
- development. Keeping it ``in the [Lisp] family'', as it were, makes
- it much easier for you and other Lisp programmers to load and use the
- bindings. Common Lisp implementations such as @acronym{CMUCL}, freed
- from having to provide a C interface to their own objects, are thus
- freed to be implemented in another language (as @acronym{CMUCL} is)
- while still allowing programmers to call foreign functions.
- @cindex minimal bindings
- Perhaps the greatest advantage is that using an @acronym{FFI} doesn't
- obligate you to become a professional binding developer. Writers of
- bindings for other languages usually end up maintaining or failing to
- maintain complete bindings to the foreign library. Using an
- @acronym{FFI}, however, means if you only need one or two functions,
- you can write bindings for only those functions, and be assured that
- you can just as easily add to the bindings if need be.
- @cindex C abstractions
- @cindex abstractions in C
- The removal of the C compiler, or C interpretation of any kind,
- creates the main disadvantage: some of C's ``abstractions'' are not
- available, violating information encapsulation. For example,
- @code{struct}s that must be passed on the stack, or used as return
- values, without corresponding functional abstractions to create and
- manage the @code{struct}s, must be declared explicitly in Lisp. This
- is fine for structs whose contents are ``public'', but is not so
- pleasant when a struct is supposed to be ``opaque'' by convention,
- even though it is not so defined.@footnote{Admittedly, this is an
- advanced issue, and we encourage you to leave this text until you are
- more familiar with how @cffi{} works.}
- Without an abstraction to create the struct, Lisp needs to be able to
- lay out the struct in memory, so must know its internal details.
- @cindex workaround for C
- In these cases, you can create a minimal C library to provide the
- missing abstractions, without destroying all the advantages of the
- Common Lisp approach discussed above. In the case of @code{struct}s,
- you can write simple, pure C functions that tell you how many bytes a
- struct requires or allocate new structs, read and write fields of the
- struct, or whatever operations are supposed to be
- public.@footnote{This does not apply to structs whose contents are
- intended to be part of the public library interface. In those cases,
- a pure Lisp struct definition is always preferred. In fact, many
- prefer to stay in Lisp and break the encapsulation anyway, placing the
- burden of correct library interface definition on the library.}
- @ref{The Groveller} automates this and other processes.
- Another disadvantage appears when you would rather use the foreign
- language than Lisp. However, someone who prefers C to Lisp is not a
- likely candidate for developing a Lisp interface to a C library.
- @node Tutorial-Getting a URL, Tutorial-Loading, Tutorial-Comparison, Tutorial
- @section Getting a @acronym{URL}
- @cindex c@acronym{URL}
- The widely available @code{libcurl} is a library for downloading files
- over protocols like @acronym{HTTP}. We will use @code{libcurl} with
- @cffi{} to download a web page.
- Please note that there are many other ways to download files from the
- web, not least the @sc{cl-curl} project to provide bindings to
- @code{libcurl} via a similar @acronym{FFI}.@footnote{Specifically,
- @acronym{UFFI}, an older @acronym{FFI} that takes a somewhat different
- approach compared to @cffi{}. I believe that these days (December
- 2005) @cffi{} is more portable and actively developed, though not as
- mature yet. Consensus in the free @sc{unix} Common Lisp community
- seems to be that @cffi{} is preferred for new development, though
- @acronym{UFFI} will likely go on for quite some time as many projects
- already use it. @cffi{} includes the @code{UFFI-COMPAT} package for
- complete compatibility with @acronym{UFFI}.}
- @uref{http://curl.haxx.se/libcurl/c/libcurl-tutorial.html,,libcurl-tutorial(3)}
- is a tutorial for @code{libcurl} programming in C. We will follow
- that to develop a binding to download a file. We will also use
- @file{curl.h}, @file{easy.h}, and the @command{man} pages for the
- @code{libcurl} function, all available in the @samp{curl-dev} package
- or equivalent for your system, or in the c@acronym{URL} source code
- package. If you have the development package, the headers should be
- installed in @file{/usr/include/curl/}, and the @command{man} pages
- may be accessed through your favorite @command{man} facility.
- @node Tutorial-Loading, Tutorial-Initializing, Tutorial-Getting a URL, Tutorial
- @section Loading foreign libraries
- @cindex loading @cffi{}
- @cindex requiring @cffi{}
- First of all, we will create a package to work in. You can save these
- forms in a file, or just send them to the listener as they are. If
- creating bindings for an @acronym{ASDF} package of yours, you will
- want to add @code{:cffi} to the @code{:depends-on} list in your
- @file{.asd} file. Otherwise, just use the @code{asdf:load-system} function to
- load @cffi{}.
- @tutorialsource{Initialization}
- @lisp
- (asdf:load-system :cffi)
- ;;; @lispcmt{Nothing special about the "CFFI-USER" package. We're just}
- ;;; @lispcmt{using it as a substitute for your own CL package.}
- (defpackage :cffi-user
- (:use :common-lisp :cffi))
- (in-package :cffi-user)
- (define-foreign-library libcurl
- (:darwin (:or "libcurl.3.dylib" "libcurl.dylib"))
- (:unix (:or "libcurl.so.3" "libcurl.so"))
- (t (:default "libcurl")))
- (use-foreign-library libcurl)
- @end lisp
- @cindex foreign library load
- @cindex library, foreign
- Using @code{define-foreign-library} and @code{use-foreign-library}, we
- have loaded @code{libcurl} into Lisp, much as the linker does when you
- start a C program, or @code{common-lisp:load} does with a Lisp source
- file or @acronym{FASL} file. We special-cased for @sc{unix} machines
- to always load a particular version, the one this tutorial was tested
- with; for those who don't care, the @code{define-foreign-library}
- clause @code{(t (:default "libcurl"))} should be satisfactory, and
- will adapt to various operating systems.
- @node Tutorial-Initializing, Tutorial-easy_setopt, Tutorial-Loading, Tutorial
- @section Initializing @code{libcurl}
- @cindex function definition
- After the introductory matter, the tutorial goes on to present the
- first function you should use.
- @example
- CURLcode curl_global_init(long flags);
- @end example
- @noindent
- Let's pick this apart into appropriate Lisp code:
- @tutorialsource{First CURLcode}
- @lisp
- ;;; @lispcmt{A CURLcode is the universal error code. curl/curl.h says}
- ;;; @lispcmt{no return code will ever be removed, and new ones will be}
- ;;; @lispcmt{added to the end.}
- (defctype curl-code :int)
- ;;; @lispcmt{Initialize libcurl with FLAGS.}
- (defcfun "curl_global_init" curl-code
- (flags :long))
- @end lisp
- @impnote{By default, CFFI assumes the UNIX viewpoint that there is one
- C symbol namespace, containing all symbols in all loaded objects.
- This is not so on Windows and Darwin, but we emulate UNIX's behaviour
- there. @ref{defcfun} for more details.}
- Note the parallels with the original C declaration. We've defined
- @code{curl-code} as a wrapping type for @code{:int}; right now, it
- only marks it as special, but later we will do something more
- interesting with it. The point is that we don't have to do it yet.
- @cindex calling foreign functions
- Looking at @file{curl.h}, @code{CURL_GLOBAL_NOTHING}, a possible value
- for @code{flags} above, is defined as @samp{0}. So we can now call
- the function:
- @example
- @sc{cffi-user>} (curl-global-init 0)
- @result{} 0
- @end example
- @cindex looks like it worked
- Looking at @file{curl.h} again, @code{0} means @code{CURLE_OK}, so it
- looks like the call succeeded. Note that @cffi{} converted the
- function name to a Lisp-friendly name. You can specify your own name
- if you want; use @code{("curl_global_init" @var{your-name-here})} as
- the @var{name} argument to @code{defcfun}.
- The tutorial goes on to have us allocate a handle. For good measure,
- we should also include the deallocator. Let's look at these
- functions:
- @example
- CURL *curl_easy_init( );
- void curl_easy_cleanup(CURL *handle);
- @end example
- Advanced users may want to define special pointer types; we will
- explore this possibility later. For now, just treat every pointer as
- the same:
- @tutorialsource{curl_easy handles}
- @lisp
- (defcfun "curl_easy_init" :pointer)
- (defcfun "curl_easy_cleanup" :void
- (easy-handle :pointer))
- @end lisp
- Now we can continue with the tutorial:
- @example
- @sc{cffi-user>} (defparameter *easy-handle* (curl-easy-init))
- @result{} *EASY-HANDLE*
- @sc{cffi-user>} *easy-handle*
- @result{} #<FOREIGN-ADDRESS #x09844EE0>
- @end example
- @cindex pointers in Lisp
- Note the print representation of a pointer. It changes depending on
- what Lisp you are using, but that doesn't make any difference to
- @cffi{}.
- @node Tutorial-easy_setopt, Tutorial-Abstraction, Tutorial-Initializing, Tutorial
- @section Setting download options
- The @code{libcurl} tutorial says we'll want to set many options before
- performing any download actions. This is done through
- @code{curl_easy_setopt}:
- @c That is literally ..., not an ellipsis.
- @example
- CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
- @end example
- @cindex varargs
- @cindex foreign arguments
- We've introduced a new twist: variable arguments. There is no obvious
- translation to the @code{defcfun} form, particularly as there are four
- possible argument types. Because of the way C works, we could define
- four wrappers around @code{curl_easy_setopt}, one for each type; in
- this case, however, we'll use the general-purpose macro
- @code{foreign-funcall} to call this function.
- @cindex enumeration, C
- To make things easier on ourselves, we'll create an enumeration of the
- kinds of options we want to set. The @code{enum CURLoption} isn't the
- most straightforward, but reading the @code{CINIT} C macro definition
- should be enlightening.
- @tutorialsource{CURLoption enumeration}
- @lisp
- (defmacro define-curl-options (name type-offsets &rest enum-args)
- "As with CFFI:DEFCENUM, except each of ENUM-ARGS is as follows:
- (NAME TYPE NUMBER)
- Where the arguments are as they are with the CINIT macro defined
- in curl.h, except NAME is a keyword.
- TYPE-OFFSETS is a plist of TYPEs to their integer offsets, as
- defined by the CURLOPTTYPE_LONG et al constants in curl.h."
- (flet ((enumerated-value (type offset)
- (+ (getf type-offsets type) offset)))
- `(progn
- (defcenum ,name
- ,@@(loop for (name type number) in enum-args
- collect (list name (enumerated-value type number))))
- ',name))) ;@lispcmt{for REPL users' sanity}
- (define-curl-options curl-option
- (long 0 objectpoint 10000 functionpoint 20000 off-t 30000)
- (:noprogress long 43)
- (:nosignal long 99)
- (:errorbuffer objectpoint 10)
- (:url objectpoint 2))
- @end lisp
- With some well-placed Emacs @code{query-replace-regexp}s, you could
- probably similarly define the entire @code{CURLoption} enumeration. I
- have selected to transcribe a few that we will use in this tutorial.
- If you're having trouble following the macrology, just macroexpand the
- @code{curl-option} definition, or see the following macroexpansion,
- conveniently downcased and reformatted:
- @tutorialsource{DEFINE-CURL-OPTIONS macroexpansion}
- @lisp
- (progn
- (defcenum curl-option
- (:noprogress 43)
- (:nosignal 99)
- (:errorbuffer 10010)
- (:url 10002))
- 'curl-option)
- @end lisp
- @noindent
- That seems more than reasonable. You may notice that we only use the
- @var{type} to compute the real enumeration offset; we will also need
- the type information later.
- First, however, let's make sure a simple call to the foreign function
- works:
- @example
- @sc{cffi-user>} (foreign-funcall "curl_easy_setopt"
- :pointer *easy-handle*
- curl-option :nosignal :long 1 curl-code)
- @result{} 0
- @end example
- @code{foreign-funcall}, despite its surface simplicity, can be used to
- call any C function. Its first argument is a string, naming the
- function to be called. Next, for each argument, we pass the name of
- the C type, which is the same as in @code{defcfun}, followed by a Lisp
- object representing the data to be passed as the argument. The final
- argument is the return type, for which we use the @code{curl-code}
- type defined earlier.
- @code{defcfun} just puts a convenient fa@,cade on
- @code{foreign-funcall}.@footnote{This isn't entirely true; some Lisps
- don't support @code{foreign-funcall}, so @code{defcfun} is implemented
- without it. @code{defcfun} may also perform optimizations that
- @code{foreign-funcall} cannot.} Our earlier call to
- @code{curl-global-init} could have been written as follows:
- @example
- @sc{cffi-user>} (foreign-funcall "curl_global_init" :long 0
- curl-code)
- @result{} 0
- @end example
- Before we continue, we will take a look at what @cffi{} can and can't
- do, and why this is so.
- @node Tutorial-Abstraction, Tutorial-Lisp easy_setopt, Tutorial-easy_setopt, Tutorial
- @section Breaking the abstraction
- @cindex breaking the abstraction
- @cindex abstraction breaking
- In @ref{Tutorial-Comparison,, What makes Lisp different}, we mentioned
- that writing an @acronym{FFI} sometimes requires depending on
- information not provided as part of the interface. The easy option
- @code{CURLOPT_WRITEDATA}, which we will not provide as part of the
- Lisp interface, illustrates this issue.
- Strictly speaking, the @code{curl-option} enumeration is not
- necessary; we could have used @code{:int 99} instead of
- @code{curl-option :nosignal} in our call to @code{curl_easy_setopt}
- above. We defined it anyway, in part to hide the fact that we are
- breaking the abstraction that the C @code{enum} provides. If the
- c@acronym{URL} developers decide to change those numbers later, we
- must change the Lisp enumeration, because enumeration values are not
- provided in the compiled C library, @code{libcurl.so.3}.
- @cffi{} works because the most useful things in C libraries ---
- non-static functions and non-static variables --- are included
- accessibly in @code{libcurl.so.3}. A C compiler that violated this
- would be considered a worthless compiler.
- The other thing @code{define-curl-options} does is give the ``type''
- of the third argument passed to @code{curl_easy_setopt}. Using this
- information, we can tell that the @code{:nosignal} option should
- accept a long integer argument. We can implicitly assume @code{t}
- @equiv{} 1 and @code{nil} @equiv{} 0, as it is in C, which takes care
- of the fact that @code{CURLOPT_NOSIGNAL} is really asking for a
- boolean.
- The ``type'' of @code{CURLOPT_WRITEDATA} is @code{objectpoint}.
- However, it is really looking for a @code{FILE*}.
- @code{CURLOPT_ERRORBUFFER} is looking for a @code{char*}, so there is
- no obvious @cffi{} type but @code{:pointer}.
- The first thing to note is that nowhere in the C interface includes
- this information; it can only be found in the manual. We could
- disjoin these clearly different types ourselves, by splitting
- @code{objectpoint} into @code{filepoint} and @code{charpoint}, but we
- are still breaking the abstraction, because we have to augment the
- entire enumeration form with this additional
- information.@footnote{Another possibility is to allow the caller to
- specify the desired C type of the third argument. This is essentially
- what happens in a call to the function written in C.}
- @cindex streams and C
- @cindex @sc{file}* and streams
- The second is that the @code{CURLOPT_WRITEDATA} argument is completely
- incompatible with the desired Lisp data, a
- stream.@footnote{@xref{Other Kinds of Streams,,, libc, GNU C Library
- Reference}, for a @acronym{GNU}-only way to extend the @code{FILE*}
- type. You could use this to convert Lisp streams to the needed C
- data. This would be quite involved and far outside the scope of this
- tutorial.} It is probably acceptable if we are controlling every file
- we might want to use as this argument, in which case we can just call
- the foreign function @code{fopen}. Regardless, though, we can't write
- to arbitrary streams, which is exactly what we want to do for this
- application.
- Finally, note that the @code{curl_easy_setopt} interface itself is a
- hack, intended to work around some of the drawbacks of C. The
- definition of @code{Curl_setopt}, while long, is far less cluttered
- than the equivalent disjoint-function set would be; in addition,
- setting a new option in an old @code{libcurl} can generate a run-time
- error rather than breaking the compile. Lisp can just as concisely
- generate functions as compare values, and the ``undefined function''
- error is just as useful as any explicit error we could define here
- might be.
- @node Tutorial-Lisp easy_setopt, Tutorial-Memory, Tutorial-Abstraction, Tutorial
- @section Option functions in Lisp
- We could use @code{foreign-funcall} directly every time we wanted to
- call @code{curl_easy_setopt}. However, we can encapsulate some of the
- necessary information with the following.
- @lisp
- ;;; @lispcmt{We will use this type later in a more creative way. For}
- ;;; @lispcmt{now, just consider it a marker that this isn't just any}
- ;;; @lispcmt{pointer.}
- (defctype easy-handle :pointer)
- (defmacro curl-easy-setopt (easy-handle enumerated-name
- value-type new-value)
- "Call `curl_easy_setopt' on EASY-HANDLE, using ENUMERATED-NAME
- as the OPTION. VALUE-TYPE is the CFFI foreign type of the third
- argument, and NEW-VALUE is the Lisp data to be translated to the
- third argument. VALUE-TYPE is not evaluated."
- `(foreign-funcall "curl_easy_setopt" easy-handle ,easy-handle
- curl-option ,enumerated-name
- ,value-type ,new-value curl-code))
- @end lisp
- Now we define a function for each kind of argument that encodes the
- correct @code{value-type} in the above. This can be done reasonably
- in the @code{define-curl-options} macroexpansion; after all, that is
- where the different options are listed!
- @cindex Lispy C functions
- We could make @code{cl:defun} forms in the expansion that simply call
- @code{curl-easy-setopt}; however, it is probably easier and clearer to
- use @code{defcfun}. @code{define-curl-options} was becoming unwieldy,
- so I defined some helpers in this new definition.
- @smalllisp
- (defun curry-curl-option-setter (function-name option-keyword)
- "Wrap the function named by FUNCTION-NAME with a version that
- curries the second argument as OPTION-KEYWORD.
- This function is intended for use in DEFINE-CURL-OPTION-SETTER."
- (setf (symbol-function function-name)
- (let ((c-function (symbol-function function-name)))
- (lambda (easy-handle new-value)
- (funcall c-function easy-handle option-keyword
- new-value)))))
- (defmacro define-curl-option-setter (name option-type
- option-value foreign-type)
- "Define (with DEFCFUN) a function NAME that calls
- curl_easy_setopt. OPTION-TYPE and OPTION-VALUE are the CFFI
- foreign type and value to be passed as the second argument to
- easy_setopt, and FOREIGN-TYPE is the CFFI foreign type to be used
- for the resultant function's third argument.
- This macro is intended for use in DEFINE-CURL-OPTIONS."
- `(progn
- (defcfun ("curl_easy_setopt" ,name) curl-code
- (easy-handle easy-handle)
- (option ,option-type)
- (new-value ,foreign-type))
- (curry-curl-option-setter ',name ',option-value)))
- (defmacro define-curl-options (type-name type-offsets &rest enum-args)
- "As with CFFI:DEFCENUM, except each of ENUM-ARGS is as follows:
- (NAME TYPE NUMBER)
- Where the arguments are as they are with the CINIT macro defined
- in curl.h, except NAME is a keyword.
- TYPE-OFFSETS is a plist of TYPEs to their integer offsets, as
- defined by the CURLOPTTYPE_LONG et al constants in curl.h.
- Also, define functions for each option named
- set-`TYPE-NAME'-`OPTION-NAME', where OPTION-NAME is the NAME from
- the above destructuring."
- (flet ((enumerated-value (type offset)
- (+ (getf type-offsets type) offset))
- ;; @lispcmt{map PROCEDURE, destructuring each of ENUM-ARGS}
- (map-enum-args (procedure)
- (mapcar (lambda (arg) (apply procedure arg)) enum-args))
- ;; @lispcmt{build a name like SET-CURL-OPTION-NOSIGNAL}
- (make-setter-name (option-name)
- (intern (concatenate
- 'string "SET-" (symbol-name type-name)
- "-" (symbol-name option-name)))))
- `(progn
- (defcenum ,type-name
- ,@@(map-enum-args
- (lambda (name type number)
- (list name (enumerated-value type number)))))
- ,@@(map-enum-args
- (lambda (name type number)
- (declare (ignore number))
- `(define-curl-option-setter ,(make-setter-name name)
- ,type-name ,name ,(ecase type
- (long :long)
- (objectpoint :pointer)
- (functionpoint :pointer)
- (off-t :long)))))
- ',type-name)))
- @end smalllisp
- @noindent
- Macroexpanding our @code{define-curl-options} form once more, we
- see something different:
- @lisp
- (progn
- (defcenum curl-option
- (:noprogress 43)
- (:nosignal 99)
- (:errorbuffer 10010)
- (:url 10002))
- (define-curl-option-setter set-curl-option-noprogress
- curl-option :noprogress :long)
- (define-curl-option-setter set-curl-option-nosignal
- curl-option :nosignal :long)
- (define-curl-option-setter set-curl-option-errorbuffer
- curl-option :errorbuffer :pointer)
- (define-curl-option-setter set-curl-option-url
- curl-option :url :pointer)
- 'curl-option)
- @end lisp
- @noindent
- Macroexpanding one of the new @code{define-curl-option-setter}
- forms yields the following:
- @lisp
- (progn
- (defcfun ("curl_easy_setopt" set-curl-option-nosignal) curl-code
- (easy-handle easy-handle)
- (option curl-option)
- (new-value :long))
- (curry-curl-option-setter 'set-curl-option-nosignal ':nosignal))
- @end lisp
- @noindent
- Finally, let's try this out:
- @example
- @sc{cffi-user>} (set-curl-option-nosignal *easy-handle* 1)
- @result{} 0
- @end example
- @noindent
- Looks like it works just as well. This interface is now reasonably
- high-level to wash out some of the ugliness of the thinnest possible
- @code{curl_easy_setopt} @acronym{FFI}, without obscuring the remaining
- C bookkeeping details we will explore.
- @node Tutorial-Memory, Tutorial-Callbacks, Tutorial-Lisp easy_setopt, Tutorial
- @section Memory management
- According to the documentation for @code{curl_easy_setopt}, the type
- of the third argument when @var{option} is @code{CURLOPT_ERRORBUFFER}
- is @code{char*}. Above, we've defined
- @code{set-curl-option-errorbuffer} to accept a @code{:pointer} as the
- new option value. However, there is a @cffi{} type @code{:string},
- which translates Lisp strings to C strings when passed as arguments to
- foreign function calls. Why not, then, use @code{:string} as the
- @cffi{} type of the third argument? There are two reasons, both
- related to the necessity of breaking abstraction described in
- @ref{Tutorial-Abstraction,, Breaking the abstraction}.
- The first reason also applies to @code{CURLOPT_URL}, which we will use
- to illustrate the point. Assuming we have changed the type of the
- third argument underlying @code{set-curl-option-url} to
- @code{:string}, look at these two equivalent forms.
- @lisp
- (set-curl-option-url *easy-handle* "http://www.cliki.net/CFFI")
- @equiv{} (with-foreign-string (url "http://www.cliki.net/CFFI")
- (foreign-funcall "curl_easy_setopt" easy-handle *easy-handle*
- curl-option :url :pointer url curl-code))
- @end lisp
- @noindent
- The latter, in fact, is mostly equivalent to what a foreign function
- call's macroexpansion actually does. As you can see, the Lisp string
- @code{"@clikicffi{}"} is copied into a @code{char} array and
- null-terminated; the pointer to beginning of this array, now a C
- string, is passed as a @cffi{} @code{:pointer} to the foreign
- function.
- @cindex dynamic extent
- @cindex foreign values with dynamic extent
- Unfortunately, the C abstraction has failed us, and we must break it.
- While @code{:string} works well for many @code{char*} arguments, it
- does not for cases like this. As the @code{curl_easy_setopt}
- documentation explains, ``The string must remain present until curl no
- longer needs it, as it doesn't copy the string.'' The C string
- created by @code{with-foreign-string}, however, only has dynamic
- extent: it is ``deallocated'' when the body (above containing the
- @code{foreign-funcall} form) exits.
- @cindex premature deallocation
- If we are supposed to keep the C string around, but it goes away, what
- happens when some @code{libcurl} function tries to access the
- @acronym{URL} string? We have reentered the dreaded world of C
- ``undefined behavior''. In some Lisps, it will probably get a chunk
- of the Lisp/C stack. You may segfault. You may get some random piece
- of other data from the heap. Maybe, in a world where ``dynamic
- extent'' is defined to be ``infinite extent'', everything will turn
- out fine. Regardless, results are likely to be almost universally
- unpleasant.@footnote{``@i{But I thought Lisp was supposed to protect
- me from all that buggy C crap!}'' Before asking a question like that,
- remember that you are a stranger in a foreign land, whose residents
- have a completely different set of values.}
- Returning to the current @code{set-curl-option-url} interface, here is
- what we must do:
- @lisp
- (let (easy-handle)
- (unwind-protect
- (with-foreign-string (url "http://www.cliki.net/CFFI")
- (setf easy-handle (curl-easy-init))
- (set-curl-option-url easy-handle url)
- #|@lispcmt{do more with the easy-handle, like actually get the URL}|#)
- (when easy-handle
- (curl-easy-cleanup easy-handle))))
- @end lisp
- @c old comment to luis: I go on to say that this isn't obviously
- @c extensible to new option settings that require C strings to stick
- @c around, as it would involve re-evaluating the unwind-protect form
- @c with more dynamic memory allocation. So I plan to show how to
- @c write something similar to ObjC's NSAutoreleasePool, to be managed
- @c with a simple unwind-protect form.
- @noindent
- That is fine for the single string defined here, but for every string
- option we want to pass, we have to surround the body of
- @code{with-foreign-string} with another @code{with-foreign-string}
- wrapper, or else do some extremely error-prone pointer manipulation
- and size calculation in advance. We could alleviate some of the pain
- with a recursively expanding macro, but this would not remove the need
- to modify the block every time we want to add an option, anathema as
- it is to a modular interface.
- Before modifying the code to account for this case, consider the other
- reason we can't simply use @code{:string} as the foreign type. In C,
- a @code{char *} is a @code{char *}, not necessarily a string. The
- option @code{CURLOPT_ERRORBUFFER} accepts a @code{char *}, but does
- not expect anything about the data there. However, it does expect
- that some @code{libcurl} function we call later can write a C string
- of up to 255 characters there. We, the callers of the function, are
- expected to read the C string at a later time, exactly the opposite of
- what @code{:string} implies.
- With the semantics for an input string in mind --- namely, that the
- string should be kept around until we @code{curl_easy_cleanup} the
- easy handle --- we are ready to extend the Lisp interface:
- @lisp
- (defvar *easy-handle-cstrings* (make-hash-table)
- "Hashtable of easy handles to lists of C strings that may be
- safely freed after the handle is freed.")
- (defun make-easy-handle ()
- "Answer a new CURL easy interface handle, to which the lifetime
- of C strings may be tied. See `add-curl-handle-cstring'."
- (let ((easy-handle (curl-easy-init)))
- (setf (gethash easy-handle *easy-handle-cstrings*) '())
- easy-handle))
- (defun free-easy-handle (handle)
- "Free CURL easy interface HANDLE and any C strings created to
- be its options."
- (curl-easy-cleanup handle)
- (mapc #'foreign-string-free
- (gethash handle *easy-handle-cstrings*))
- (remhash handle *easy-handle-cstrings*))
- (defun add-curl-handle-cstring (handle cstring)
- "Add CSTRING to be freed when HANDLE is, answering CSTRING."
- (car (push cstring (gethash handle *easy-handle-cstrings*))))
- @end lisp
- @noindent
- Here we have redefined the interface to create and free handles, to
- associate a list of allocated C strings with each handle while it
- exists. The strategy of using different function names to wrap around
- simple foreign functions is more common than the solution implemented
- earlier with @code{curry-curl-option-setter}, which was to modify the
- function name's function slot.@footnote{There are advantages and
- disadvantages to each approach; I chose to @code{(setf
- symbol-function)} earlier because it entailed generating fewer magic
- function names.}
- Incidentally, the next step is to redefine
- @code{curry-curl-option-setter} to allocate C strings for the
- appropriate length of time, given a Lisp string as the
- @code{new-value} argument:
- @lisp
- (defun curry-curl-option-setter (function-name option-keyword)
- "Wrap the function named by FUNCTION-NAME with a version that
- curries the second argument as OPTION-KEYWORD.
- This function is intended for use in DEFINE-CURL-OPTION-SETTER."
- (setf (symbol-function function-name)
- (let ((c-function (symbol-function function-name)))
- (lambda (easy-handle new-value)
- (funcall c-function easy-handle option-keyword
- (if (stringp new-value)
- (add-curl-handle-cstring
- easy-handle
- (foreign-string-alloc new-value))
- new-value))))))
- @end lisp
- @noindent
- A quick analysis of the code shows that you need only reevaluate the
- @code{curl-option} enumeration definition to take advantage of these
- new semantics. Now, for good measure, let's reallocate the handle
- with the new functions we just defined, and set its @acronym{URL}:
- @example
- @sc{cffi-user>} (curl-easy-cleanup *easy-handle*)
- @result{} NIL
- @sc{cffi-user>} (setf *easy-handle* (make-easy-handle))
- @result{} #<FOREIGN-ADDRESS #x09844EE0>
- @sc{cffi-user>} (set-curl-option-nosignal *easy-handle* 1)
- @result{} 0
- @sc{cffi-user>} (set-curl-option-url *easy-handle*
- "http://www.cliki.net/CFFI")
- @result{} 0
- @end example
- @cindex strings
- For fun, let's inspect the Lisp value of the C string that was created
- to hold @code{"@clikicffi{}"}. By virtue of the implementation of
- @code{add-curl-handle-cstring}, it should be accessible through the
- hash table defined:
- @example
- @sc{cffi-user>} (foreign-string-to-lisp
- (car (gethash *easy-handle* *easy-handle-cstrings*)))
- @result{} "http://www.cliki.net/CFFI"
- @end example
- @noindent
- Looks like that worked, and @code{libcurl} now knows what
- @acronym{URL} we want to retrieve.
- Finally, we turn back to the @code{:errorbuffer} option mentioned at
- the beginning of this section. Whereas the abstraction added to
- support string inputs works fine for cases like @code{CURLOPT_URL}, it
- hides the detail of keeping the C string; for @code{:errorbuffer},
- however, we need that C string.
- In a moment, we'll define something slightly cleaner, but for now,
- remember that you can always hack around anything. We're modifying
- handle creation, so make sure you free the old handle before
- redefining @code{free-easy-handle}.
- @smalllisp
- (defvar *easy-handle-errorbuffers* (make-hash-table)
- "Hashtable of easy handles to C strings serving as error
- writeback buffers.")
- ;;; @lispcmt{An extra byte is very little to pay for peace of mind.}
- (defparameter *curl-error-size* 257
- "Minimum char[] size used by cURL to report errors.")
- (defun make-easy-handle ()
- "Answer a new CURL easy interface handle, to which the lifetime
- of C strings may be tied. See `add-curl-handle-cstring'."
- (let ((easy-handle (curl-easy-init)))
- (setf (gethash easy-handle *easy-handle-cstrings*) '())
- (setf (gethash easy-handle *easy-handle-errorbuffers*)
- (foreign-alloc :char :count *curl-error-size*
- :initial-element 0))
- easy-handle))
- (defun free-easy-handle (handle)
- "Free CURL easy interface HANDLE and any C strings created to
- be its options."
- (curl-easy-cleanup handle)
- (foreign-free (gethash handle *easy-handle-errorbuffers*))
- (remhash handle *easy-handle-errorbuffers*)
- (mapc #'foreign-string-free
- (gethash handle *easy-handle-cstrings*))
- (remhash handle *easy-handle-cstrings*))
- (defun get-easy-handle-error (handle)
- "Answer a string containing HANDLE's current error message."
- (foreign-string-to-lisp
- (gethash handle *easy-handle-errorbuffers*)))
- @end smalllisp
- Be sure to once again set the options we've set thus far. You may
- wish to define yet another wrapper function to do this.
- @node Tutorial-Callbacks, Tutorial-Completion, Tutorial-Memory, Tutorial
- @section Calling Lisp from C
- If you have been reading
- @uref{http://curl.haxx.se/libcurl/c/curl_easy_setopt.html,,
- @code{curl_easy_setopt(3)}}, you should have noticed that some options
- accept a function pointer. In particular, we need one function
- pointer to set as @code{CURLOPT_WRITEFUNCTION}, to be called by
- @code{libcurl} rather than the reverse, in order to receive data as it
- is downloaded.
- A binding writer without the aid of @acronym{FFI} usually approaches
- this problem by writing a C function that accepts C data, converts to
- the language's internal objects, and calls the callback provided by
- the user, again in a reverse of usual practices.
- The @cffi{} approach to callbacks precisely mirrors its differences
- with the non-@acronym{FFI} approach on the ``calling C from Lisp''
- side, which we have dealt with exclusively up to now. That is, you
- define a callback function in Lisp using @code{defcallback}, and
- @cffi{} effectively creates a C function to be passed as a function
- pointer.
- @impnote{This is much trickier than calling C functions from Lisp, as
- it literally involves somehow generating a new C function that is as
- good as any created by the compiler. Therefore, not all Lisps support
- them. @xref{Implementation Support}, for information about @cffi{}
- support issues in this and other areas. You may want to consider
- changing to a Lisp that supports callbacks in order to continue with
- this tutorial.}
- @cindex callback definition
- @cindex defining callbacks
- Defining a callback is very similar to defining a callout; the main
- difference is that we must provide some Lisp forms to be evaluated as
- part of the callback. Here is the signature for the function the
- @code{:writefunction} option takes:
- @example
- size_t
- @var{function}(void *ptr, size_t size, size_t nmemb, void *stream);
- @end example
- @impnote{size_t is almost always an unsigned int. You can get this
- and many other types using feature tests for your system by using
- cffi-grovel.}
- The above signature trivially translates into a @cffi{}
- @code{defcallback} form, as follows.
- @lisp
- ;;; @lispcmt{Alias in case size_t changes.}
- (defctype size :unsigned-int)
- ;;; @lispcmt{To be set as the CURLOPT_WRITEFUNCTION of every easy handle.}
- (defcallback easy-write size ((ptr :pointer) (size size)
- (nmemb size) (stream :pointer))
- (let ((data-size (* size nmemb)))
- (handler-case
- ;; @lispcmt{We use the dynamically-bound *easy-write-procedure* to}
- ;; @lispcmt{call a closure with useful lexical context.}
- (progn (funcall (symbol-value '*easy-write-procedure*)
- (foreign-string-to-lisp ptr :count data-size))
- data-size) ;@lispcmt{indicates success}
- ;; @lispcmt{The WRITEFUNCTION should return something other than the}
- ;; @lispcmt{#bytes available to signal an error.}
- (error () (if (zerop data-size) 1 0)))))
- @end lisp
- First, note the correlation of the first few forms, used to declare
- the C function's signature, with the signature in C syntax. We
- provide a Lisp name for the function, its return type, and a name and
- type for each argument.
- In the body, we call the dynamically-bound
- @code{*easy-write-procedure*} with a ``finished'' translation, of
- pulling together the raw data and size into a Lisp string, rather than
- deal with the data directly. As part of calling
- @code{curl_easy_perform} later, we'll bind that variable to a closure
- with more useful lexical bindings than the top-level
- @code{defcallback} form.
- Finally, we make a halfhearted effort to prevent non-local exits from
- unwinding the C stack, covering the most likely case with an
- @code{error} handler, which is usually triggered
- unexpectedly.@footnote{Unfortunately, we can't protect against
- @emph{all} non-local exits, such as @code{return}s and @code{throw}s,
- because @code{unwind-protect} cannot be used to ``short-circuit'' a
- non-local exit in Common Lisp, due to proposal @code{minimal} in
- @uref{http://www.lisp.org/HyperSpec/Issues/iss152-writeup.html,
- @acronym{ANSI} issue @sc{Exit-Extent}}. Furthermore, binding an
- @code{error} handler prevents higher-up code from invoking restarts
- that may be provided under the callback's dynamic context. Such is
- the way of compromise.} The reason is that most C code is written to
- understand its own idiosyncratic error condition, implemented above in
- the case of @code{curl_easy_perform}, and more ``undefined behavior''
- can result if we just wipe C stack frames without allowing them to
- execute whatever cleanup actions as they like.
- Using the @code{CURLoption} enumeration in @file{curl.h} once more, we
- can describe the new option by modifying and reevaluating
- @code{define-curl-options}.
- @lisp
- (define-curl-options curl-option
- (long 0 objectpoint 10000 functionpoint 20000 off-t 30000)
- (:noprogress long 43)
- (:nosignal long 99)
- (:errorbuffer objectpoint 10)
- (:url objectpoint 2)
- (:writefunction functionpoint 11)) ;@lispcmt{new item here}
- @end lisp
- Finally, we can use the defined callback and the new
- @code{set-curl-option-writefunction} to finish configuring the easy
- handle, using the @code{callback} macro to retrieve a @cffi{}
- @code{:pointer}, which works like a function pointer in C code.
- @example
- @sc{cffi-user>} (set-curl-option-writefunction
- *easy-handle* (callback easy-write))
- @result{} 0
- @end example
- @node Tutorial-Completion, Tutorial-Types, Tutorial-Callbacks, Tutorial
- @section A complete @acronym{FFI}?
- @c TeX goes insane on @uref{@clikicffi{}}
- With all options finally set and a medium-level interface developed,
- we can finish the definition and retrieve
- @uref{http://www.cliki.net/CFFI}, as is done in the tutorial.
- @lisp
- (defcfun "curl_easy_perform" curl-code
- (handle easy-handle))
- @end lisp
- @example
- @sc{cffi-user>} (with-output-to-string (contents)
- (let ((*easy-write-procedure*
- (lambda (string)
- (write-string string contents))))
- (declare (special *easy-write-procedure*))
- (curl-easy-perform *easy-handle*)))
- @result{} "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"
- @enddots{}
- Now fear, comprehensively</P>
- "
- @end example
- Of course, that itself is slightly unwieldy, so you may want to define
- a function around it that simply retrieves a @acronym{URL}. I will
- leave synthesis of all the relevant @acronym{REPL} forms presented
- thus far into a single function as an exercise for the reader.
- The remaining sections of this tutorial explore some advanced features
- of @cffi{}; the definition of new types will receive special
- attention. Some of these features are essential for particular
- foreign function calls; some are very helpful when trying to develop a
- Lispy interface to C.
- @node Tutorial-Types, Tutorial-Conclusion, Tutorial-Completion, Tutorial
- @section Defining new types
- We've occasionally used the @code{defctype} macro in previous sections
- as a kind of documentation, much what you'd use @code{typedef} for in
- C. We also tried one special kind of type definition, the
- @code{defcenum} type. @xref{defcstruct}, for a definition macro that
- may come in handy if you need to use C @code{struct}s as data.
- @cindex type definition
- @cindex data in Lisp and C
- @cindex translating types
- However, all of these are mostly sugar for the powerful underlying
- foreign type interface called @dfn{type translators}. You can easily
- define new translators for any simple named foreign type. Since we've
- defined the new type @code{curl-code} to use as the return type for
- various @code{libcurl} functions, we can use that to directly convert
- c@acronym{URL} errors to Lisp errors.
- @code{defctype}'s purpose is to define simple @code{typedef}-like
- aliases. In order to use @dfn{type translators} we must use the
- @code{define-foreign-type} macro. So let's redefine @code{curl-code}
- using it.
- @lisp
- (define-foreign-type curl-code-type ()
- ()
- (:actual-type :int)
- (:simple-parser curl-code))
- @end lisp
- @code{define-foreign-type} is a thin wrapper around @code{defclass}.
- For now, all you need to know in the context of this example is that
- it does what @code{(defctype curl-code :int)} would do and,
- additionally, defines a new class @code{curl-code-type} which we will
- take advantage of shortly.
- The @code{CURLcode} enumeration seems to follow the typical error code
- convention of @samp{0} meaning all is well, and each non-zero integer
- indicating a different kind of error. We can apply that trivially to
- differentiate between normal exits and error exits.
- @lisp
- (define-condition curl-code-error (error)
- (($code :initarg :curl-code :reader curl-error-code))
- (:report (lambda (c stream)
- (format stream "libcurl function returned error ~A"
- (curl-error-code c))))
- (:documentation "Signalled when a libcurl function answers
- a code other than CURLE_OK."))
- (defmethod translate-from-foreign (value (type curl-code-type))
- "Raise a CURL-CODE-ERROR if VALUE, a curl-code, is non-zero."
- (if (zerop value)
- :curle-ok
- (error 'curl-code-error :curl-code value)))
- @end lisp
- @noindent
- The heart of this translator is new method
- @code{translate-from-foreign}. By specializing the @var{type}
- parameter on @code{curl-code-type}, we immediately modify the behavior
- of every function that returns a @code{curl-code} to pass the result
- through this new method.
- To see the translator in action, try invoking a function that returns
- a @code{curl-code}. You need to reevaluate the respective
- @code{defcfun} form so that it picks up the new @code{curl-code}
- definition.
- @example
- @sc{cffi-user>} (set-curl-option-nosignal *easy-handle* 1)
- @result{} :CURLE-OK
- @end example
- @noindent
- As the result was @samp{0}, the new method returned @code{:curle-ok},
- just as specified.@footnote{It might be better to return
- @code{(values)} than @code{:curle-ok} in real code, but this is good
- for illustration.} I will leave disjoining the separate
- @code{CURLcode}s into condition types and improving the @code{:report}
- function as an exercise for you.
- The creation of @code{*easy-handle-cstrings*} and
- @code{*easy-handle-errorbuffers*} as properties of @code{easy-handle}s
- is a kluge. What we really want is a Lisp structure that stores these
- properties along with the C pointer. Unfortunately,
- @code{easy-handle} is currently just a fancy name for the foreign type
- @code{:pointer}; the actual pointer object varies from Common Lisp
- implementation to implementation, needing only to satisfy
- @code{pointerp} and be returned from @code{make-pointer} and friends.
- One solution that would allow us to define a new Lisp structure to
- represent @code{easy-handle}s would be to write a wrapper around every
- function that currently takes an @code{easy-handle}; the wrapper would
- extract the pointer and pass it to the foreign function. However, we
- can use type translators to more elegantly integrate this
- ``translation'' into the foreign function calling framework, using
- @code{translate-to-foreign}.
- @smalllisp
- (defclass easy-handle ()
- ((pointer :initform (curl-easy-init)
- :documentation "Foreign pointer from curl_easy_init")
- (error-buffer
- :initform (foreign-alloc :char :count *curl-error-size*
- :initial-element 0)
- :documentation "C string describing last error")
- (c-strings :initform '()
- :documentation "C strings set as options"))
- (:documentation "I am a parameterization you may pass to
- curl-easy-perform to perform a cURL network protocol request."))
- (defmethod initialize-instance :after ((self easy-handle) &key)
- (set-curl-option-errorbuffer self (slot-value self 'error-buffer)))
- (defun add-curl-handle-cstring (handle cstring)
- "Add CSTRING to be freed when HANDLE is, answering CSTRING."
- (car (push cstring (slot-value handle 'c-strings))))
- (defun get-easy-handle-error (handle)
- "Answer a string containing HANDLE's current error message."
- (foreign-string-to-lisp
- (slot-value handle 'error-buffer)))
- (defun free-easy-handle (handle)
- "Free CURL easy interface HANDLE and any C strings created to
- be its options."
- (with-slots (pointer error-buffer c-strings) handle
- (curl-easy-cleanup pointer)
- (foreign-free error-buffer)
- (mapc #'foreign-string-free c-strings)))
- (define-foreign-type easy-handle-type ()
- ()
- (:actual-type :pointer)
- (:simple-parser easy-handle))
- (defmethod translate-to-foreign (handle (type easy-handle-type))
- "Extract the pointer from an easy-HANDLE."
- (slot-value handle 'pointer))
- @end smalllisp
- While we changed some of the Lisp functions defined earlier to use
- @acronym{CLOS} slots rather than hash tables, the foreign functions
- work just as well as they did before.
- @cindex limitations of type translators
- The greatest strength, and the greatest limitation, of the type
- translator comes from its generalized interface. As stated
- previously, we could define all foreign function calls in terms of the
- primitive foreign types provided by @cffi{}. The type translator
- interface allows us to cleanly specify the relationship between Lisp
- and C data, independent of where it appears in a function call. This
- independence comes at a price; for example, it cannot be used to
- modify translation semantics based on other arguments to a function
- call. In these cases, you should rely on other features of Lisp,
- rather than the powerful, yet domain-specific, type translator
- interface.
- @node Tutorial-Conclusion, , Tutorial-Types, Tutorial
- @section What's next?
- @cffi{} provides a rich and powerful foundation for communicating with
- foreign libraries; as we have seen, it is up to you to make that
- experience a pleasantly Lispy one. This tutorial does not cover all
- the features of @cffi{}; please see the rest of the manual for
- details. In particular, if something seems obviously missing, it is
- likely that either code or a good reason for lack of code is already
- present.
- @impnote{There are some other things in @cffi{} that might deserve
- tutorial sections, such as free-translated-object, or structs. Let us
- know which ones you care about.}
- @c ===================================================================
- @c CHAPTER: Wrapper generators
- @node Wrapper generators, Foreign Types, Tutorial, Top
- @chapter Wrapper generators
- @cffi{}'s interface is designed for human programmers, being aimed at
- aesthetic as well as technical sophistication. However, there are a
- few programs aimed at translating C and C++ header files, or
- approximations thereof, into @cffi{} forms constituting a foreign
- interface to the symbols in those files.
- These wrapper generators are known to support output of @cffi{} forms.
- @table @asis
- @item @uref{http://www.cliki.net/Verrazano,Verrazano}
- Designed specifically for Common Lisp. Uses @acronym{GCC}'s parser
- output in @acronym{XML} format to discover functions, variables, and
- other header file data. This means you need @acronym{GCC} to generate
- forms; on the other hand, the parser employed is mostly compliant with
- @acronym{ANSI} C.
- @item @uref{http://www.cliki.net/SWIG,SWIG}
- A foreign interface generator originally designed to generate Python
- bindings, it has been ported to many other systems, including @cffi{}
- in version 1.3.28. Includes its own C declaration munger, not
- intended to be fully-compliant with @acronym{ANSI} C.
- @end table
- First, this manual does not describe use of these other programs; they
- have documentation of their own. If you have problems using a
- generated interface, please look at the output @cffi{} forms and
- verify that they are a correct @cffi{} interface to the library in
- question; if they are correct, contact @cffi{} developers with
- details, keeping in mind that they communicate in terms of those forms
- rather than any particular wrapper generator. Otherwise, contact the
- maintainers of the wrapper generator you are using, provided you can
- reasonably expect more accuracy from the generator.
- When is more accuracy an unreasonable expectation? As described in
- the tutorial (@pxref{Tutorial-Abstraction,, Breaking the
- abstraction}), the information in C declarations is insufficient to
- completely describe every interface. In fact, it is quite common to
- run into an interface that cannot be handled automatically, and
- generators should be excused from generating a complete interface in
- these cases.
- As further described in the tutorial, the thinnest Lisp interface to a
- C function is not always the most pleasant one. In many cases, you
- will want to manually write a Lispier interface to the C functions
- that interest you.
- Wrapper generators should be treated as time-savers, not complete
- automation of the full foreign interface writing job. Reports of the
- amount of work done by generators vary from 30% to 90%. The
- incremental development style enabled by @cffi{} generally reduces
- this proportion below that for languages like Python.
- @c Where I got the above 30-90% figures:
- @c 30%: lemonodor's post about SWIG
- @c 90%: Balooga on #lisp. He said 99%, but that's probably an
- @c exaggeration (leave it to me to pass judgement :)
- @c -stephen
- @c ===================================================================
- @c CHAPTER: Foreign Types
- @node Foreign Types, Pointers, Wrapper generators, Top
- @chapter Foreign Types
- Foreign types describe how data is translated back and forth between C
- and Lisp. @cffi{} provides various built-in types and allows the user to
- define new types.
- @menu
- * Built-In Types::
- * Other Types::
- * Defining Foreign Types::
- * Foreign Type Translators::
- * Optimizing Type Translators::
- * Foreign Structure Types::
- * Allocating Foreign Objects::
- Dictionary
- * convert-from-foreign::
- * convert-to-foreign::
- * defbitfield::
- * defcstruct::
- * defcunion::
- * defctype::
- * defcenum::
- @c * define-type-spec-parser::
- * define-foreign-type::
- * define-parse-method::
- @c * explain-foreign-slot-value:
- * foreign-bitfield-symbols::
- * foreign-bitfield-value::
- * foreign-enum-keyword::
- * foreign-enum-value::
- * foreign-slot-names::
- * foreign-slot-offset::
- * foreign-slot-pointer::
- * foreign-slot-value::
- * foreign-type-alignment::
- * foreign-type-size::
- * free-converted-object::
- * free-translated-object::
- * translate-from-foreign::
- * translate-to-foreign::
- * translate-into-foreign-memory::
- * with-foreign-slots::
- @end menu
- @node Built-In Types, Other Types, Foreign Types, Foreign Types
- @section Built-In Types
- @ForeignType{:char}
- @ForeignType{:unsigned-char}
- @ForeignType{:short}
- @ForeignType{:unsigned-short}
- @ForeignType{:int}
- @ForeignType{:unsigned-int}
- @ForeignType{:long}
- @ForeignType{:unsigned-long}
- @ForeignType{:long-long}
- @ForeignType{:unsigned-long-long}
- These types correspond to the native C integer types according to the
- @acronym{ABI} of the Lisp implementation's host system.
- @code{:long-long} and @code{:unsigned-long-long} are not supported
- natively on all implementations. However, they are emulated by
- @code{mem-ref} and @code{mem-set}.
- When those types are @strong{not} available, the symbol
- @code{cffi-sys::no-long-long} is pushed into @code{*features*}.
- @ForeignType{:uchar}
- @ForeignType{:ushort}
- @ForeignType{:uint}
- @ForeignType{:ulong}
- @ForeignType{:llong}
- @ForeignType{:ullong}
- For convenience, the above types are provided as shortcuts for
- @code{unsigned-char}, @code{unsigned-short}, @code{unsigned-int},
- @code{unsigned-long}, @code{long-long} and @code{unsigned-long-long},
- respectively.
- @ForeignType{:int8}
- @ForeignType{:uint8}
- @ForeignType{:int16}
- @ForeignType{:uint16}
- @ForeignType{:int32}
- @ForeignType{:uint32}
- @ForeignType{:int64}
- @ForeignType{:uint64}
- @ForeignType{:size}
- @ForeignType{:ssize}
- @ForeignType{:intptr}
- @ForeignType{:uintptr}
- @ForeignType{:ptrdiff}
- @ForeignType{:offset}
- Foreign integer types of specific sizes, corresponding to the C types
- defined in @code{stdint.h}.
- @c @ForeignType{:time}
- @c Foreign integer types corresponding to the standard C types (without
- @c the @code{_t} suffix).
- @c @impnote{These are not implemented yet. --luis}
- @c @impnote{I'm sure there are more of these that could be useful, let's
- @c add any types that can't be defined portably to this list as
- @c necessary. --james}
- @ForeignType{:float}
- @ForeignType{:double}
- On all systems, the @code{:float} and @code{:double} types represent a
- C @code{float} and @code{double}, respectively. On most but not all
- systems, @code{:float} and @code{:double} represent a Lisp
- @code{single-float} and @code{double-float}, respectively. It is not
- so useful to consider the relationship between Lisp types and C types
- as isomorphic, as simply to recognize the relationship, and relative
- precision, among each respective category.
- @ForeignType{:long-double}
- This type is only supported on SCL.
- @ForeignType{:pointer &optional type}
- A foreign pointer to an object of any type, corresponding to
- @code{void *}. You can optionally specify type of pointer
- (e.g. @code{(:pointer :char)}). Although @cffi{} won't do anything
- with that information yet, it is useful for documentation purposes.
- @ForeignType{:void}
- No type at all. Only valid as the return type of a function.
- @node Other Types, Defining Foreign Types, Built-In Types, Foreign Types
- @section Other Types
- @cffi{} also provides a few useful types that aren't built-in C
- types.
- @ForeignType{:string}
- The @code{:string} type performs automatic conversion between Lisp and
- C strings. Note that, in the case of functions the converted C string
- will have dynamic extent (i.e.@: it will be automatically freed after
- the foreign function returns).
- In addition to Lisp strings, this type will accept foreign pointers
- and pass them unmodified.
- A method for @ref{free-translated-object} is specialized for this
- type. So, for example, foreign strings allocated by this type and
- passed to a foreign function will be freed after the function
- returns.
- @lisp
- CFFI> (foreign-funcall "getenv" :string "SHELL" :string)
- @result{} "/bin/bash"
- CFFI> (with-foreign-string (str "abcdef")
- (foreign-funcall "strlen" :string str :int))
- @result{} 6
- @end lisp
- @ForeignType{:string+ptr}
- Like @code{:string} but returns a list with two values when convert
- from C to Lisp: a Lisp string and the C string's foreign pointer.
- @lisp
- CFFI> (foreign-funcall "getenv" :string "SHELL" :string+ptr)
- @result{} ("/bin/bash" #.(SB-SYS:INT-SAP #XBFFFFC6F))
- @end lisp
- @ForeignType{:boolean &optional (base-type :int)}
- The @code{:boolean} type converts between a Lisp boolean and a C
- boolean. It canonicalizes to @var{base-type} which is @code{:int} by
- default.
- @lisp
- (convert-to-foreign nil :boolean) @result{} 0
- (convert-to-foreign t :boolean) @result{} 1
- (convert-from-foreign 0 :boolean) @result{} nil
- (convert-from-foreign 1 :boolean) @result{} t
- @end lisp
- @ForeignType{:bool}
- The @code{:bool} type represents the C99 @code{_Bool} or C++
- @code{bool}. Its size is usually 1 byte except on OSX where it's an
- @code{int}.
- @ForeignType{:wrapper base-type &key to-c from-c}
- The @code{:wrapper} type stores two symbols passed to the @var{to-c}
- and @var{from-c} arguments. When a value is being translated to or
- from C, this type @code{funcall}s the respective symbol.
- @code{:wrapper} types will be typedefs for @var{base-type} and will
- inherit its translators, if any.
- Here's an example of how the @code{:boolean} type could be defined in
- terms of @code{:wrapper}.
- @lisp
- (defun bool-c-to-lisp (value)
- (not (zerop value)))
- (defun bool-lisp-to-c (value)
- (if value 1 0))
- (defctype my-bool (:wrapper :int :from-c bool-c-to-lisp
- :to-c bool-lisp-to-c))
- (convert-to-foreign nil 'my-bool) @result{} 0
- (convert-from-foreign 1 'my-bool) @result{} t
- @end lisp
- @node Defining Foreign Types, Foreign Type Translators, Other Types, Foreign Types
- @section Defining Foreign Types
- You can define simple C-like @code{typedef}s through the
- @code{defctype} macro. Defining a typedef is as simple as giving
- @code{defctype} a new name and the name of the type to be wrapped.
- @lisp
- ;;; @lispcmt{Define MY-INT as an alias for the built-in type :INT.}
- (defctype my-int :int)
- @end lisp
- With this type definition, one can, for instance, declare arguments to
- foreign functions as having the type @code{my-int}, and they will be
- passed as integers.
- @subheading More complex types
- @cffi{} offers another way to define types through
- @code{define-foreign-type}, a thin wrapper macro around
- @code{defclass}. As an example, let's go through the steps needed to
- define a @code{(my-string &key encoding)} type. First, we need to
- define our type class:
- @lisp
- (define-foreign-type my-string-type ()
- ((encoding :reader string-type-encoding :initarg :encoding))
- (:actual-type :pointer))
- @end lisp
- The @code{:actual-type} class option tells CFFI that this type will
- ultimately be passed to and received from foreign code as a
- @code{:pointer}. Now you need to tell CFFI how to parse a type
- specification such as @code{(my-string :encoding :utf8)} into an
- instance of @code{my-string-type}. We do that with
- @code{define-parse-method}:
- @lisp
- (define-parse-method my-string (&key (encoding :utf-8))
- (make-instance 'my-string-type :encoding encoding))
- @end lisp
- The next section describes how make this type actually translate
- between C and Lisp strings.
- @node Foreign Type Translators, Optimizing Type Translators, Defining Foreign Types, Foreign Types
- @section Foreign Type Translators
- Type translators are used to automatically convert Lisp values to or
- from foreign values. For example, using type translators, one can
- take the @code{my-string} type defined in the previous section and
- specify that it should:
- @itemize
- @item
- convert C strings to Lisp strings;
- @item
- convert Lisp strings to newly allocated C strings;
- @item
- free said C strings when they are no longer needed.
- @end itemize
- In order to tell @cffi{} how to automatically convert Lisp values to
- foreign values, define a specialized method for the
- @code{translate-to-foreign} generic function:
- @lisp
- ;;; @lispcmt{Define a method that converts Lisp strings to C strings.}
- (defmethod translate-to-foreign (string (type my-string-type))
- (foreign-string-alloc string :encoding (string-type-encoding type)))
- @end lisp
- @noindent
- From now on, whenever an object is passed as a @code{my-string} to a
- foreign function, this method will be invoked to convert the Lisp
- value. To perform the inverse operation, which is needed for functions
- that return a @code{my-string}, specialize the
- @code{translate-from-foreign} generic function in the same manner:
- @lisp
- ;;; @lispcmt{Define a method that converts C strings to Lisp strings.}
- (defmethod translate-from-foreign (pointer (type my-string-type))
- (foreign-string-to-lisp pointer :encoding (string-type-encoding type)))
- @end lisp
- @noindent
- When a @code{translate-to-foreign} method requires allocation of
- foreign memory, you must also define a @code{free-translated-object}
- method to free the memory once the foreign object is no longer needed,
- otherwise you'll be faced with memory leaks. This generic function is
- called automatically by @cffi{} when passing objects to foreign
- functions. Let's do that:
- @lisp
- ;;; @lispcmt{Free strings allocated by translate-to-foreign.}
- (defmethod free-translated-object (pointer (type my-string-type) param)
- (declare (ignore param))
- (foreign-string-free pointer))
- @end lisp
- @noindent
- In this specific example, we don't need the @var{param} argument, so
- we ignore it. See @ref{free-translated-object}, for an explanation of
- its purpose and how you can use it.
- A type translator does not necessarily need to convert the value. For
- example, one could define a typedef for @code{:pointer} that ensures,
- in the @code{translate-to-foreign} method, that the value is not a
- null pointer, signalling an error if a null pointer is passed. This
- would prevent some pointer errors when calling foreign functions that
- cannot handle null pointers.
- @strong{Please note:} these methods are meant as extensible hooks
- only, and you should not call them directly. Use
- @code{convert-to-foreign}, @code{convert-from-foreign} and
- @code{free-converted-object} instead.
- @xref{Tutorial-Types,, Defining new types}, for another example of
- type translators.
- @node Optimizing Type Translators, Foreign Structure Types, Foreign Type Translators, Foreign Types
- @section Optimizing Type Translators
- @cindex type translators, optimizing
- @cindex compiler macros for type translation
- @cindex defining type-translation compiler macros
- Being based on generic functions, the type translation mechanism
- described above can add a bit of overhead. This is usually not
- significant, but we nevertheless provide a way of getting rid of the
- overhead for the cases where it matters.
- A good way to understand this issue is to look at the code generated
- by @code{defcfun}. Consider the following example using the previously
- defined @code{my-string} type:
- @lisp
- CFFI> (macroexpand-1 '(defcfun foo my-string (x my-string)))
- ;; @lispcmt{(simplified, downcased, etc...)}
- (defun foo (x)
- (multiple-value-bind (#:G2019 #:PARAM3149)
- (translate-to-foreign x #<MY-STRING-TYPE @{11ED5A79@}>)
- (unwind-protect
- (translate-from-foreign
- (foreign-funcall "foo" :pointer #:G2019 :pointer)
- #<MY-STRING-TYPE @{11ED5659@}>)
- (free-translated-object #:G2019 #<MY-STRING-TYPE @{11ED51A79@}>
- #:PARAM3149))))
- @end lisp
- @noindent
- In order to get rid of those generic function calls, @cffi{} has
- another set of extensible generic functions that provide functionality
- similar to @acronym{CL}'s compiler macros:
- @code{expand-to-foreign-dyn}, @code{expand-to-foreign} and
- @code{expand-from-foreign}. Here's how one could define a
- @code{my-boolean} with them:
- @lisp
- (define-foreign-type my-boolean-type ()
- ()
- (:actual-type :int)
- (:simple-parser my-boolean))
- (defmethod expand-to-foreign (value (type my-boolean-type))
- `(if ,value 1 0))
- (defmethod expand-from-foreign (value (type my-boolean-type))
- `(not (zerop ,value)))
- @end lisp
- @noindent
- And here's what the macroexpansion of a function using this type would
- look like:
- @lisp
- CFFI> (macroexpand-1 '(defcfun bar my-boolean (x my-boolean)))
- ;; @lispcmt{(simplified, downcased, etc...)}
- (defun bar (x)
- (let ((#:g3182 (if x 1 0)))
- (not (zerop (foreign-funcall "bar" :int #:g3182 :int)))))
- @end lisp
- @noindent
- No generic function overhead.
- Let's go back to our @code{my-string} type. The expansion interface
- has no equivalent of @code{free-translated-object}; you must instead
- define a method on @code{expand-to-foreign-dyn}, the third generic
- function in this interface. This is especially useful when you can
- allocate something much more efficiently if you know the object has
- dynamic extent, as is the case with function calls that don't save the
- relevant allocated arguments.
- This exactly what we need for the @code{my-string} type:
- @lisp
- (defmethod expand-from-foreign (form (type my-string-type))
- `(foreign-string-to-lisp ,form))
- (defmethod expand-to-foreign-dyn (value var body (type my-string-type))
- (let ((encoding (string-type-encoding type)))
- `(with-foreign-string (,var ,value :encoding ',encoding)
- ,@@body)))
- @end lisp
- @noindent
- So let's look at the macro expansion:
- @lisp
- CFFI> (macroexpand-1 '(defcfun foo my-string (x my-string)))
- ;; @lispcmt{(simplified, downcased, etc...)}
- (defun foo (x)
- (with-foreign-string (#:G2021 X :encoding ':utf-8)
- (foreign-string-to-lisp
- (foreign-funcall "foo" :pointer #:g2021 :pointer))))
- @end lisp
- @noindent
- Again, no generic function overhead.
- @subheading Other details
- To short-circuit expansion and use the @code{translate-*} functions
- instead, simply call the next method. Return its result in cases
- where your method cannot generate an appropriate replacement for it.
- This analogous to the @code{&whole form} mechanism compiler macros
- provide.
- The @code{expand-*} methods have precedence over their
- @code{translate-*} counterparts and are guaranteed to be used in
- @code{defcfun}, @code{foreign-funcall}, @code{defcvar} and
- @code{defcallback}. If you define a method on each of the
- @code{expand-*} generic functions, you are guaranteed to have full
- control over the expressions generated for type translation in these
- macros.
- They may or may not be used in other @cffi{} operators that need to
- translate between Lisp and C data; you may only assume that
- @code{expand-*} methods will probably only be called during Lisp
- compilation.
- @code{expand-to-foreign-dyn} has precedence over
- @code{expand-to-foreign} and is only used in @code{defcfun} and
- @code{foreign-funcall}, only making sense in those contexts.
- @strong{Important note:} this set of generic functions is called at
- macroexpansion time. Methods are defined when loaded or evaluated,
- not compiled. You are responsible for ensuring that your
- @code{expand-*} methods are defined when the @code{foreign-funcall} or
- other forms that use them are compiled. One way to do this is to put
- the method definitions earlier in the file and inside an appropriate
- @code{eval-when} form; another way is to always load a separate Lisp
- or @acronym{FASL} file containing your @code{expand-*} definitions
- before compiling files with forms that ought to use them. Otherwise,
- they will not be found and the runtime translators will be used
- instead.
- @node Foreign Structure Types, Allocating Foreign Objects, Optimizing Type Translators, Foreign Types
- @section Foreign Structure Types
- For more involved C types than simple aliases to built-in types, such
- as you can make with @code{defctype}, @cffi{} allows declaration of
- structures and unions with @code{defcstruct} and @code{defcunion}.
- For example, consider this fictional C structure declaration holding
- some personal information:
- @example
- struct person @{
- int number;
- char* reason;
- @};
- @end example
- @noindent
- The equivalent @code{defcstruct} form follows:
- @lisp
- (defcstruct person
- (number :int)
- (reason :string))
- @end lisp
- @c LMH structure translation
- By default, @ref{convert-from-foreign} (and also @ref{mem-ref}) will
- make a plist with slot names as keys, and @ref{convert-to-foreign} will
- translate such a plist to a foreign structure. A user wishing to define
- other translations should use the @code{:class} argument to
- @ref{defcstruct}, and then define methods for
- @ref{translate-from-foreign} and
- @ref{translate-into-foreign-memory} that specialize on this class,
- possibly calling @code{call-next-method} to translate from and to the
- plists rather than provide a direct interface to the foreign object.
- The macro @code{translation-forms-for-class} will generate the forms
- necessary to translate a Lisp class into a foreign structure and vice
- versa.
- @c Write separate function doc section for translation-forms-for-class?
- @c Examples, perhaps taken from the tests?
- Please note that this interface is only for those that must know about
- the values contained in a relevant struct. If the library you are
- interfacing returns an opaque pointer that needs only be passed to
- other C library functions, by all means just use @code{:pointer} or a
- type-safe definition munged together with @code{defctype} and type
- translation. To pass or return a structure by value to a function, load
- the cffi-libffi system and specify the structure as @code{(:struct
- @var{structure-name})}. To pass or return the pointer, you can use
- either @code{:pointer} or @code{(:pointer (:struct
- @var{structure-name}))}.
- @subheading Optimizing translate-into-foreign-memory
- Just like how @ref{translate-from-foreign} had
- @code{expand-from-foreign} to optimize away the generic function call
- and @ref{translate-to-foreign} had the same in
- @code{expand-to-foreign}, @ref{translate-into-foreign-memory} has
- @code{expand-into-foreign-memory}.
- Let's use our @code{person} struct in an example. However, we are
- going to spice it up by using a lisp struct rather than a plist to
- represent the person in lisp.
- First we redefine @code{person} very slightly.
- @lisp
- (defcstruct (person :class c-person)
- (number :int)
- (reason :string))
- @end lisp
- By adding @code{:class} we can specialize the @code{translate-*}
- methods on the type @code{c-person}.
- Next we define a lisp struct to use instead of the plists.
- @lisp
- (defstruct lisp-person
- (number 0 :type integer)
- (reason "" :type string))
- @end lisp
- And now let's define the type translators we know already:
- @lisp
- (defmethod translate-from-foreign (ptr (type c-person))
- (with-foreign-slots ((number reason) ptr (:struct person))
- (make-lisp-person :number number :reason reason)))
- (defmethod expand-from-foreign (ptr (type c-person))
- `(with-foreign-slots ((number reason) ,ptr (:struct person))
- (make-lisp-person :number number :reason reason)))
- (defmethod translate-into-foreign-memory (value (type c-person) ptr)
- (with-foreign-slots ((number reason) ptr (:struct person))
- (setf number (lisp-person-number value)
- reason (lisp-person-reason value))))
- @end lisp
- At this point everything works, we can convert to and from our
- @code{lisp-person} and foreign @code{person}. If we macroexpand
- @lisp
- (setf (mem-aref ptr '(:struct person)) x)
- @end lisp
- we get something like:
- @lisp
- (let ((#:store879 x))
- (translate-into-foreign-memory #:store879 #<c-person person>
- (inc-pointer ptr 0))
- #:store879)
- @end lisp
- Which is good, but now we can do better and get rid of that generic
- function call to @code{translate-into-foreign-memory}.
- @lisp
- (defmethod expand-into-foreign-memory (value (type c-person) ptr)
- `(with-foreign-slots ((number reason) ,ptr (:struct person))
- (setf number (lisp-person-number ,value)
- reason (lisp-person-reason ,value))))
- @end lisp
- Now we can expand again so see the changes:
- @lisp
- ;; this:
- (setf (mem-aref ptr '(:struct person)) x)
- ;; expands to this
- ;; (simplified, downcased, etc..)
- (let ((#:store887 x))
- (with-foreign-slots ((number reason) (inc-pointer ptr 0) (:struct person))
- (setf number (lisp-person-number #:store887)
- reason (lisp-person-reason #:store887))) #:store887)
- @end lisp
- And there we are, no generic function overhead.
- @subheading Compatibility note
- Previous versions of CFFI accepted the
- ``bare'' @var{structure-name} as a type specification, which was
- interpreted as a pointer to the structure. This is deprecated and
- produces a style warning. Using this deprecated form means that
- @ref{mem-aref} retains its prior meaning and returns a pointer. Using
- the @code{(:struct @var{structure-name})} form for the type,
- @ref{mem-aref} provides a Lisp object translated from the
- structure (by default a plist). Thus the semantics are consistent with all
- types in returning the object as represented in Lisp, and not a pointer,
- with the exception of the ``bare'' structure compatibility retained.
- In order to obtain the pointer, you should use the function @ref{mem-aptr}.
- See @ref{defcstruct} for more details.
- @node Allocating Foreign Objects, convert-from-foreign, Foreign Structure Types, Foreign Types
- @section Allocating Foreign Objects
- @c I moved this because I moved with-foreign-object to the Pointers
- @c chapter, where foreign-alloc is.
- @xref{Allocating Foreign Memory}.
- @c ===================================================================
- @c CONVERT-FROM-FOREIGN
- @page
- @node convert-from-foreign, convert-to-foreign, Allocating Foreign Objects, Foreign Types
- @heading convert-from-foreign
- @subheading Syntax
- @Function{convert-from-foreign foreign-value type @res{} value}
- @subheading Arguments and Values
- @table @var
- @item foreign-value
- The primitive C value as returned from a primitive foreign function or
- from @code{convert-to-foreign}.
- @item type
- A @cffi{} type specifier.
- @item value
- The Lisp value translated from @var{foreign-value}.
- @end table
- @subheading Description
- This is an external interface to the type translation facility. In
- the implementation, all foreign functions are ultimately defined as
- type translation wrappers around primitive foreign function
- invocations.
- This function is available mostly for inspection of the type
- translation process, and possibly optimization of special cases of
- your foreign function calls.
- Its behavior is better described under @code{translate-from-foreign}'s
- documentation.
- @subheading Examples
- @lisp
- CFFI-USER> (convert-to-foreign "a boat" :string)
- @result{} #<FOREIGN-ADDRESS #x097ACDC0>
- @result{} T
- CFFI-USER> (convert-from-foreign * :string)
- @result{} "a boat"
- @end lisp
- @subheading See Also
- @seealso{convert-to-foreign} @*
- @seealso{free-converted-object} @*
- @seealso{translate-from-foreign}
- @c ===================================================================
- @c CONVERT-TO-FOREIGN
- @page
- @node convert-to-foreign, defbitfield, convert-from-foreign, Foreign Types
- @heading convert-to-foreign
- @subheading Syntax
- @Function{convert-to-foreign value type @res{} foreign-value, alloc-params}
- @subheading Arguments and Values
- @table @var
- @item value
- The Lisp object to be translated to a foreign object.
- @item type
- A @cffi{} type specifier.
- @item foreign-value
- The primitive C value, ready to be passed to a primitive foreign
- function.
- @item alloc-params
- Something of a translation state; you must pass it to
- @code{free-converted-object} along with the foreign value for that to
- work.
- @end table
- @subheading Description
- This is an external interface to the type translation facility. In
- the implementation, all foreign functions are ultimately defined as
- type translation wrappers around primitive foreign function
- invocations.
- This function is available mostly for inspection of the type
- translation process, and possibly optimization of special cases of
- your foreign function calls.
- Its behavior is better described under @code{translate-to-foreign}'s
- documentation.
- @subheading Examples
- @lisp
- CFFI-USER> (convert-to-foreign t :boolean)
- @result{} 1
- @result{} NIL
- CFFI-USER> (convert-to-foreign "hello, world" :string)
- @result{} #<FOREIGN-ADDRESS #x097C5F80>
- @result{} T
- CFFI-USER> (code-char (mem-aref * :char 5))
- @result{} #\,
- @end lisp
- @subheading See Also
- @seealso{convert-from-foreign} @*
- @seealso{free-converted-object} @*
- @seealso{translate-to-foreign}
- @c ===================================================================
- @c DEFBITFIELD
- @page
- @node defbitfield, defcstruct, convert-to-foreign, Foreign Types
- @heading defbitfield
- @subheading Syntax
- @Macro{defbitfield name-and-options &body masks}
- masks ::= [docstring] @{ (symbol value) @}* @*
- name-and-options ::= name | (name &optional (base-type :int)) @*
- @subheading Arguments and Values
- @table @var
- @item name
- The name of the new bitfield type.
- @item docstring
- A documentation string, ignored.
- @item base-type
- A symbol denoting a foreign type.
- @item symbol
- A Lisp symbol.
- @item value
- An integer representing a bitmask.
- @end table
- @subheading Description
- The @code{defbitfield} macro is used to define foreign types that map
- lists of symbols to integer values.
- If @var{value} is omitted, it will be computed as follows: find the
- greatest @var{value} previously used, including those so computed,
- with only a single 1-bit in its binary representation (that is, powers
- of two), and left-shift it by one. This rule guarantees that a
- computed @var{value} cannot clash with previous values, but may clash
- with future explicitly specified values.
- Symbol lists will be automatically converted to values and vice versa
- when being passed as arguments to or returned from foreign functions,
- respectively. The same applies to any other situations where an object
- of a bitfield type is expected.
- Types defined with @code{defbitfield} canonicalize to @var{base-type}
- which is @code{:int} by default.
- @subheading Examples
- @lisp
- (defbitfield open-flags
- (:rdonly #x0000)
- :wronly ;@lispcmt{#x0001}
- :rdwr ;@lispcmt{@dots{}}
- :nonblock
- :append
- (:creat #x0200))
- ;; @lispcmt{etc@dots{}}
- CFFI> (foreign-bitfield-symbols 'open-flags #b1101)
- @result{} (:WRONLY :NONBLOCK :APPEND)
- CFFI> (foreign-bitfield-value 'open-flags '(:rdwr :creat))
- @result{} 514 ; #x0202
- (defcfun ("open" unix-open) :int
- (path :string)
- (flags open-flags)
- (mode :uint16)) ; unportable
- CFFI> (unix-open "/tmp/foo" '(:wronly :creat) #o644)
- @result{} #<an fd>
- ;;; @lispcmt{Consider also the following lispier wrapper around open()}
- (defun lispier-open (path mode &rest flags)
- (unix-open path flags mode))
- @end lisp
- @subheading See Also
- @seealso{foreign-bitfield-value} @*
- @seealso{foreign-bitfield-symbols}
- @c ===================================================================
- @c DEFCSTRUCT
- @page
- @node defcstruct, defcunion, defbitfield, Foreign Types
- @heading defcstruct
- @subheading Syntax
- @Macro{defcstruct name-and-options &body doc-and-slots @res{} name}
- name-and-options ::= structure-name | (structure-name &key size) @*
- doc-and-slots ::= [docstring] @{ (slot-name slot-type &key count offset) @}*
- @subheading Arguments and Values
- @table @var
- @item structure-name
- The name of new structure type.
- @item docstring
- A documentation string, ignored.
- @item slot-name
- A symbol naming the slot. It must be unique among slot names in this
- structure.
- @item size
- Use this option to override the size (in bytes) of the struct.
- @item slot-type
- The type specifier for the slot.
- @item count
- Used to declare an array of size @var{count} inside the
- structure. Defaults to @code{1} as such an array and a single element
- are semantically equivalent.
- @item offset
- Overrides the slot's offset. The next slot's offset is calculated
- based on this one.
- @end table
- @subheading Description
- This defines a new @cffi{} aggregate type akin to C @code{struct}s.
- In other words, it specifies that foreign objects of the type
- @var{structure-name} are groups of different pieces of data, or
- ``slots'', of the @var{slot-type}s, distinguished from each other by
- the @var{slot-name}s. Each structure is located in memory at a
- position, and the slots are allocated sequentially beginning at that
- point in memory (with some padding allowances as defined by the C
- @acronym{ABI}, unless otherwise requested by specifying an
- @var{offset} from the beginning of the structure (offset 0).
- In other words, it is isomorphic to the C @code{struct}, giving
- several extra features.
- There are two kinds of slots, for the two kinds of @cffi{} types:
- @table @dfn
- @item Simple
- Contain a single instance of a type that canonicalizes to a built-in
- type, such as @code{:long} or @code{:pointer}. Used for simple
- @cffi{} types.
- @item Aggregate
- Contain an embedded structure or union, or an array of objects. Used
- for aggregate @cffi{} types.
- @end table
- The use of @acronym{CLOS} terminology for the structure-related
- features is intentional; structure definitions are very much like
- classes with (far) fewer features.
- @subheading Examples
- @lisp
- (defcstruct point
- "Point structure."
- (x :int)
- (y :int))
- CFFI> (with-foreign-object (ptr 'point)
- ;; @lispcmt{Initialize the slots}
- (setf (foreign-slot-value ptr 'point 'x) 42
- (foreign-slot-value ptr 'point 'y) 42)
- ;; @lispcmt{Return a list with the coordinates}
- (with-foreign-slots ((x y) ptr point)
- (list x y)))
- @result{} (42 42)
- @end lisp
- @lisp
- ;; @lispcmt{Using the :size and :offset options to define a partial structure.}
- ;; @lispcmt{(this is useful when you are interested in only a few slots}
- ;; @lispcmt{of a big foreign structure)}
- (defcstruct (foo :size 32)
- "Some struct with 32 bytes."
- ; @lispcmt{<16 bytes we don't care about>}
- (x :int :offset 16) ; @lispcmt{an int at offset 16}
- (y :int) ; @lispcmt{another int at offset 16+sizeof(int)}
- ; @lispcmt{<a couple more bytes we don't care about>}
- (z :char :offset 24)) ; @lispcmt{a char at offset 24}
- ; @lispcmt{<7 more bytes ignored (since size is 32)>}
- CFFI> (foreign-type-size 'foo)
- @result{} 32
- @end lisp
- @lisp
- ;;; @lispcmt{Using :count to define arrays inside of a struct.}
- (defcstruct video_tuner
- (name :char :count 32))
- @end lisp
- @subheading See Also
- @seealso{foreign-slot-pointer} @*
- @seealso{foreign-slot-value} @*
- @seealso{with-foreign-slots}
- @c ===================================================================
- @c DEFCUNION
- @page
- @node defcunion, defctype, defcstruct, Foreign Types
- @heading defcunion
- @subheading Syntax
- @Macro{defcunion name &body doc-and-slots @res{} name}
- doc-and-slots ::= [docstring] @{ (slot-name slot-type &key count) @}*
- @subheading Arguments and Values
- @table @var
- @item name
- The name of new union type.
- @item docstring
- A documentation string, ignored.
- @item slot-name
- A symbol naming the slot.
- @item slot-type
- The type specifier for the slot.
- @item count
- Used to declare an array of size @var{count} inside the
- structure.
- @end table
- @subheading Description
- A union is a structure in which all slots have an offset of zero. It
- is isomorphic to the C @code{union}. Therefore, you should use the
- usual foreign structure operations for accessing a union's slots.
- @subheading Examples
- @lisp
- (defcunion uint32-bytes
- (int-value :unsigned-int)
- (bytes :unsigned-char :count 4))
- @end lisp
- @subheading See Also
- @seealso{foreign-slot-pointer} @*
- @seealso{foreign-slot-value}
- @c ===================================================================
- @c DEFCTYPE
- @page
- @node defctype, defcenum, defcunion, Foreign Types
- @heading defctype
- @subheading Syntax
- @Macro{defctype name base-type &optional documentation}
- @subheading Arguments and Values
- @table @var
- @item name
- The name of the new foreign type.
- @item base-type
- A symbol or a list defining the new type.
- @item documentation
- A documentation string, currently ignored.
- @end table
- @subheading Description
- The @code{defctype} macro provides a mechanism similar to C's
- @code{typedef} to define new types. The new type inherits
- @var{base-type}'s translators, if any. There is no way to define
- translations for types defined with @code{defctype}. For that,
- you should use @ref{define-foreign-type}.
- @subheading Examples
- @lisp
- (defctype my-string :string
- "My own string type.")
- (defctype long-bools (:boolean :long)
- "Booleans that map to C longs.")
- @end lisp
- @subheading See Also
- @seealso{define-foreign-type}
- @c ===================================================================
- @c DEFCENUM
- @page
- @node defcenum, define-foreign-type, defctype, Foreign Types
- @heading defcenum
- @subheading Syntax
- @Macro{defcenum name-and-options &body enum-list}
- enum-list ::= [docstring] @{ keyword | (keyword value) @}* @*
- name-and-options ::= name | (name &optional (base-type :int) &key allow-undeclared-values) @*
- @subheading Arguments and Values
- @table @var
- @item name
- The name of the new enum type.
- @item docstring
- A documentation string, ignored.
- @item base-type
- A symbol denoting a foreign type.
- @item allow-undeclared-values
- Whether to pass through integer values that were not explicitly declared
- in the enum when translating from foreign memory.
- @item keyword
- A keyword symbol.
- @item value
- An index value for a keyword.
- @end table
- @subheading Description
- The @code{defcenum} macro is used to define foreign types that map
- keyword symbols to integer values, similar to the C @code{enum} type.
- If @var{value} is omitted its value will either be 0, if it's the
- first entry, or it it will continue the progression from the last
- specified value.
- Keywords will be automatically converted to values and vice-versa when
- being passed as arguments to or returned from foreign functions,
- respectively. The same applies to any other situations where an object
- of an @code{enum} type is expected.
- If a value should be translated to lisp that is not declared in the
- enum, an error will be signalled. You can elide this error and instead
- make it pass the original enum value by specifying
- @var{allow-undeclared-values}. This can be useful for very large
- enumerations of which we only care about a subset of values, or for
- enumerations that should allow for client or vendor extensions that we
- cannot know about.
- Types defined with @code{defcenum} canonicalize to @var{base-type}
- which is @code{:int} by default.
- @subheading Examples
- @lisp
- (defcenum boolean
- :no
- :yes)
- CFFI> (foreign-enum-value 'boolean :no)
- @result{} 0
- @end lisp
- @lisp
- (defcenum numbers
- (:one 1)
- :two
- (:four 4))
- CFFI> (foreign-enum-keyword 'numbers 2)
- @result{} :TWO
- @end lisp
- @subheading See Also
- @seealso{foreign-enum-value} @*
- @seealso{foreign-enum-keyword}
- @c ===================================================================
- @c DEFINE-FOREIGN-TYPE
- @page
- @node define-foreign-type, define-parse-method, defcenum, Foreign Types
- @heading define-foreign-type
- @subheading Syntax
- @Macro{define-foreign-type class-name supers slots &rest options @res{} class-name}
- options ::= (@code{:actual-type} @var{type}) | @
- (@code{:simple-parser} @var{symbol}) | @
- @emph{regular defclass option}
- @subheading Arguments and Values
- @table @var
- @item class-name
- A symbol naming the new foreign type class.
- @item supers
- A list of symbols naming the super classes.
- @item slots
- A list of slot definitions, passed to @code{defclass}.
- @end table
- @subheading Description
- @c TODO rewrite
- The macro @code{define-foreign-type} defines a new class
- @var{class-name}. It is a thin wrapper around @code{defclass}. Among
- other things, it ensures that @var{class-name} becomes a subclass of
- @var{foreign-type}, what you need to know about that is that there's
- an initarg @code{:actual-type} which serves the same purpose as
- @code{defctype}'s @var{base-type} argument.
- @c TODO mention the type translators here
- @c FIX FIX
- @subheading Examples
- Taken from @cffi{}'s @code{:boolean} type definition:
- @lisp
- (define-foreign-type :boolean (&optional (base-type :int))
- "Boolean type. Maps to an :int by default. Only accepts integer types."
- (ecase base-type
- ((:char
- :unsigned-char
- :int
- :unsigned-int
- :long
- :unsigned-long) base-type)))
- CFFI> (canonicalize-foreign-type :boolean)
- @result{} :INT
- CFFI> (canonicalize-foreign-type '(:boolean :long))
- @result{} :LONG
- CFFI> (canonicalize-foreign-type '(:boolean :float))
- ;; @lispcmt{@error{} signalled by ECASE.}
- @end lisp
- @subheading See Also
- @seealso{defctype} @*
- @seealso{define-parse-method}
- @c ===================================================================
- @c DEFINE-PARSE-METHOD
- @page
- @node define-parse-method, foreign-bitfield-symbols, define-foreign-type, Foreign Types
- @heading define-parse-method
- @subheading Syntax
- @Macro{define-parse-method name lambda-list &body body @res{} name}
- @subheading Arguments and Values
- @table @var
- @item type-name
- A symbol naming the new foreign type.
- @item lambda-list
- A lambda list which is the argument list of the new foreign type.
- @item body
- One or more forms that provide a definition of the new foreign type.
- @end table
- @subheading Description
- @c TODO: update example. The boolean type is probably a good choice.
- @subheading Examples
- Taken from @cffi{}'s @code{:boolean} type definition:
- @lisp
- (define-foreign-type :boolean (&optional (base-type :int))
- "Boolean type. Maps to an :int by default. Only accepts integer types."
- (ecase base-type
- ((:char
- :unsigned-char
- :int
- :unsigned-int
- :long
- :unsigned-long) base-type)))
- CFFI> (canonicalize-foreign-type :boolean)
- @result{} :INT
- CFFI> (canonicalize-foreign-type '(:boolean :long))
- @result{} :LONG
- CFFI> (canonicalize-foreign-type '(:boolean :float))
- ;; @lispcmt{@error{} signalled by ECASE.}
- @end lisp
- @subheading See Also
- @seealso{define-foreign-type}
- @c ===================================================================
- @c EXPLAIN-FOREIGN-SLOT-VALUE
- @c @node explain-foreign-slot-value
- @c @heading explain-foreign-slot-value
- @c @subheading Syntax
- @c @Macro{explain-foreign-slot-value ptr type &rest slot-names}
- @c @subheading Arguments and Values
- @c @table @var
- @c @item ptr
- @c ...
- @c @item type
- @c ...
- @c @item slot-names
- @c ...
- @c @end table
- @c @subheading Description
- @c This macro translates the slot access that would occur by calling
- @c @code{foreign-slot-value} with the same arguments into an equivalent
- @c expression in C and prints it to @code{*standard-output*}.
- @c @emph{Note: this is not implemented yet.}
- @c @subheading Examples
- @c @lisp
- @c CFFI> (explain-foreign-slot-value ptr 'timeval 'tv-secs)
- @c @result{} ptr->tv_secs
- @c CFFI> (explain-foreign-slot-value emp 'employee 'hire-date 'tv-usecs)
- @c @result{} emp->hire_date.tv_usecs
- @c @end lisp
- @c @subheading See Also
- @c ===================================================================
- @c FOREIGN-BITFIELD-SYMBOLS
- @page
- @node foreign-bitfield-symbols, foreign-bitfield-value, define-parse-method, Foreign Types
- @heading foreign-bitfield-symbols
- @subheading Syntax
- @Function{foreign-bitfield-symbols type value @res{} symbols}
- @subheading Arguments and Values
- @table @var
- @item type
- A bitfield type.
- @item value
- An integer.
- @item symbols
- A potentially shared list of symbols.
- @code{nil}.
- @end table
- @subheading Description
- The function @code{foreign-bitfield-symbols} returns a possibly shared
- list of symbols that correspond to @var{value} in @var{type}.
- @subheading Examples
- @lisp
- (defbitfield flags
- (flag-a 1)
- (flag-b 2)
- (flag-c 4))
- CFFI> (foreign-bitfield-symbols 'flags #b101)
- @result{} (FLAG-A FLAG-C)
- @end lisp
- @subheading See Also
- @seealso{defbitfield} @*
- @seealso{foreign-bitfield-value}
- @c ===================================================================
- @c FOREIGN-BITFIELD-VALUE
- @page
- @node foreign-bitfield-value, foreign-enum-keyword, foreign-bitfield-symbols, Foreign Types
- @heading foreign-bitfield-value
- @subheading Syntax
- @Function{foreign-bitfield-value type symbols @res{} value}
- @subheading Arguments and Values
- @table @var
- @item type
- A @code{bitfield} type.
- @item symbol
- A Lisp symbol.
- @item value
- An integer.
- @end table
- @subheading Description
- The function @code{foreign-bitfield-value} returns the @var{value} that
- corresponds to the symbols in the @var{symbols} list.
- @subheading Examples
- @lisp
- (defbitfield flags
- (flag-a 1)
- (flag-b 2)
- (flag-c 4))
- CFFI> (foreign-bitfield-value 'flags '(flag-a flag-c))
- @result{} 5 ; #b101
- @end lisp
- @subheading See Also
- @seealso{defbitfield} @*
- @seealso{foreign-bitfield-symbols}
- @c ===================================================================
- @c FOREIGN-ENUM-KEYWORD
- @page
- @node foreign-enum-keyword, foreign-enum-value, foreign-bitfield-value, Foreign Types
- @heading foreign-enum-keyword
- @subheading Syntax
- @Function{foreign-enum-keyword type value &key errorp @res{} keyword}
- @subheading Arguments and Values
- @table @var
- @item type
- An @code{enum} type.
- @item value
- An integer.
- @item errorp
- If true (the default), signal an error if @var{value} is not defined
- in @var{type}. If false, @code{foreign-enum-keyword} returns
- @code{nil}.
- @item keyword
- A keyword symbol.
- @end table
- @subheading Description
- The function @code{foreign-enum-keyword} returns the keyword symbol
- that corresponds to @var{value} in @var{type}.
- An error is signaled if @var{type} doesn't contain such @var{value}
- and @var{errorp} is true.
- @subheading Examples
- @lisp
- (defcenum boolean
- :no
- :yes)
- CFFI> (foreign-enum-keyword 'boolean 1)
- @result{} :YES
- @end lisp
- @subheading See Also
- @seealso{defcenum} @*
- @seealso{foreign-enum-value}
- @c ===================================================================
- @c FOREIGN-ENUM-VALUE
- @page
- @node foreign-enum-value, foreign-slot-names, foreign-enum-keyword, Foreign Types
- @heading foreign-enum-value
- @subheading Syntax
- @Function{foreign-enum-value type keyword &key errorp @res{} value}
- @subheading Arguments and Values
- @table @var
- @item type
- An @code{enum} type.
- @item keyword
- A keyword symbol.
- @item errorp
- If true (the default), signal an error if @var{keyword} is not
- defined in @var{type}. If false, @code{foreign-enum-value} returns
- @code{nil}.
- @item value
- An integer.
- @end table
- @subheading Description
- The function @code{foreign-enum-value} returns the @var{value} that
- corresponds to @var{keyword} in @var{type}.
- An error is signaled if @var{type} doesn't contain such
- @var{keyword}, and @var{errorp} is true.
- @subheading Examples
- @lisp
- (defcenum boolean
- :no
- :yes)
- CFFI> (foreign-enum-value 'boolean :yes)
- @result{} 1
- @end lisp
- @subheading See Also
- @seealso{defcenum} @*
- @seealso{foreign-enum-keyword}
- @c ===================================================================
- @c FOREIGN-SLOT-NAMES
- @page
- @node foreign-slot-names, foreign-slot-offset, foreign-enum-value, Foreign Types
- @heading foreign-slot-names
- @subheading Syntax
- @Function{foreign-slot-names type @res{} names}
- @subheading Arguments and Values
- @table @var
- @item type
- A foreign struct type.
- @item names
- A list.
- @end table
- @subheading Description
- The function @code{foreign-slot-names} returns a potentially shared
- list of slot @var{names} for the given structure @var{type}. This list
- has no particular order.
- @subheading Examples
- @lisp
- (defcstruct timeval
- (tv-secs :long)
- (tv-usecs :long))
- CFFI> (foreign-slot-names '(:struct timeval))
- @result{} (TV-SECS TV-USECS)
- @end lisp
- @subheading See Also
- @seealso{defcstruct} @*
- @seealso{foreign-slot-offset} @*
- @seealso{foreign-slot-value} @*
- @seealso{foreign-slot-pointer}
- @c ===================================================================
- @c FOREIGN-SLOT-OFFSET
- @page
- @node foreign-slot-offset, foreign-slot-pointer, foreign-slot-names, Foreign Types
- @heading foreign-slot-offset
- @subheading Syntax
- @Function{foreign-slot-offset type slot-name @res{} offset}
- @subheading Arguments and Values
- @table @var
- @item type
- A foreign struct type.
- @item slot-name
- A symbol.
- @item offset
- An integer.
- @end table
- @subheading Description
- The function @code{foreign-slot-offset} returns the @var{offset} in
- bytes of a slot in a foreign struct type.
- @subheading Examples
- @lisp
- (defcstruct timeval
- (tv-secs :long)
- (tv-usecs :long))
- CFFI> (foreign-slot-offset '(:struct timeval) 'tv-secs)
- @result{} 0
- CFFI> (foreign-slot-offset '(:struct timeval) 'tv-usecs)
- @result{} 4
- @end lisp
- @subheading See Also
- @seealso{defcstruct} @*
- @seealso{foreign-slot-names} @*
- @seealso{foreign-slot-pointer} @*
- @seealso{foreign-slot-value}
- @c ===================================================================
- @c FOREIGN-SLOT-POINTER
- @page
- @node foreign-slot-pointer, foreign-slot-value, foreign-slot-offset, Foreign Types
- @heading foreign-slot-pointer
- @subheading Syntax
- @Function{foreign-slot-pointer ptr type slot-name @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A pointer to a structure.
- @item type
- A foreign structure type.
- @item slot-names
- A slot name in the @var{type}.
- @item pointer
- A pointer to the slot @var{slot-name}.
- @end table
- @subheading Description
- Returns a pointer to the location of the slot @var{slot-name} in a
- foreign object of type @var{type} at @var{ptr}. The returned pointer
- points inside the structure. Both the pointer and the memory it points
- to have the same extent as @var{ptr}.
- For aggregate slots, this is the same value returned by
- @code{foreign-slot-value}.
- @subheading Examples
- @lisp
- (defcstruct point
- "Pointer structure."
- (x :int)
- (y :int))
- CFFI> (with-foreign-object (ptr '(:struct point))
- (foreign-slot-pointer ptr '(:struct point) 'x))
- @result{} #<FOREIGN-ADDRESS #xBFFF6E60>
- ;; @lispcmt{Note: the exact pointer representation varies from lisp to lisp.}
- @end lisp
- @subheading See Also
- @seealso{defcstruct} @*
- @seealso{foreign-slot-value} @*
- @seealso{foreign-slot-names} @*
- @seealso{foreign-slot-offset}
- @c ===================================================================
- @c FOREIGN-SLOT-VALUE
- @page
- @node foreign-slot-value, foreign-type-alignment, foreign-slot-pointer, Foreign Types
- @heading foreign-slot-value
- @subheading Syntax
- @Accessor{foreign-slot-value ptr type slot-name @res{} object}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A pointer to a structure.
- @item type
- A foreign structure type.
- @item slot-name
- A symbol naming a slot in the structure type.
- @item object
- The object contained in the slot specified by @var{slot-name}.
- @end table
- @subheading Description
- For simple slots, @code{foreign-slot-value} returns the value of the
- object, such as a Lisp integer or pointer. In C, this would be
- expressed as @code{ptr->slot}.
- For aggregate slots, a pointer inside the structure to the beginning
- of the slot's data is returned. In C, this would be expressed as
- @code{&ptr->slot}. This pointer and the memory it points to have the
- same extent as @var{ptr}.
- There are compiler macros for @code{foreign-slot-value} and its
- @code{setf} expansion that open code the memory access when
- @var{type} and @var{slot-names} are constant at compile-time.
- @subheading Examples
- @lisp
- (defcstruct point
- "Pointer structure."
- (x :int)
- (y :int))
- CFFI> (with-foreign-object (ptr '(:struct point))
- ;; @lispcmt{Initialize the slots}
- (setf (foreign-slot-value ptr '(:struct point) 'x) 42
- (foreign-slot-value ptr '(:struct point) 'y) 42)
- ;; @lispcmt{Return a list with the coordinates}
- (with-foreign-slots ((x y) ptr (:struct point))
- (list x y)))
- @result{} (42 42)
- @end lisp
- @subheading See Also
- @seealso{defcstruct} @*
- @seealso{foreign-slot-names} @*
- @seealso{foreign-slot-offset} @*
- @seealso{foreign-slot-pointer} @*
- @seealso{with-foreign-slots}
- @c ===================================================================
- @c FOREIGN-TYPE-ALIGNMENT
- @page
- @node foreign-type-alignment, foreign-type-size, foreign-slot-value, Foreign Types
- @heading foreign-type-alignment
- @subheading Syntax
- @c XXX: This is actually a generic function.
- @Function{foreign-type-alignment type @res{} alignment}
- @subheading Arguments and Values
- @table @var
- @item type
- A foreign type.
- @item alignment
- An integer.
- @end table
- @subheading Description
- The function @code{foreign-type-alignment} returns the
- @var{alignment} of @var{type} in bytes.
- @subheading Examples
- @lisp
- CFFI> (foreign-type-alignment :char)
- @result{} 1
- CFFI> (foreign-type-alignment :short)
- @result{} 2
- CFFI> (foreign-type-alignment :int)
- @result{} 4
- @end lisp
- @lisp
- (defcstruct foo
- (a :char))
- CFFI> (foreign-type-alignment '(:struct foo))
- @result{} 1
- @end lisp
- @subheading See Also
- @seealso{foreign-type-size}
- @c ===================================================================
- @c FOREIGN-TYPE-SIZE
- @page
- @node foreign-type-size, free-converted-object, foreign-type-alignment, Foreign Types
- @heading foreign-type-size
- @subheading Syntax
- @c XXX: this is actually a generic function.
- @Function{foreign-type-size type @res{} size}
- @subheading Arguments and Values
- @table @var
- @item type
- A foreign type.
- @item size
- An integer.
- @end table
- @subheading Description
- The function @code{foreign-type-size} return the @var{size} of
- @var{type} in bytes. This includes any padding within and following
- the in-memory representation as needed to create an array of
- @var{type} objects.
- @subheading Examples
- @lisp
- (defcstruct foo
- (a :double)
- (c :char))
- CFFI> (foreign-type-size :double)
- @result{} 8
- CFFI> (foreign-type-size :char)
- @result{} 1
- CFFI> (foreign-type-size '(:struct foo))
- @result{} 16
- @end lisp
- @subheading See Also
- @seealso{foreign-type-alignment}
- @c ===================================================================
- @c FREE-CONVERTED-OBJECT
- @page
- @node free-converted-object, free-translated-object, foreign-type-size, Foreign Types
- @heading free-converted-object
- @subheading Syntax
- @Function{free-converted-object foreign-value type params}
- @subheading Arguments and Values
- @table @var
- @item foreign-value
- The C object to be freed.
- @item type
- A @cffi{} type specifier.
- @item params
- The state returned as the second value from @code{convert-to-foreign};
- used to implement the third argument to @code{free-translated-object}.
- @end table
- @subheading Description
- The return value is unspecified.
- This is an external interface to the type translation facility. In
- the implementation, all foreign functions are ultimately defined as
- type translation wrappers around primitive foreign function
- invocations.
- This function is available mostly for inspection of the type
- translation process, and possibly optimization of special cases of
- your foreign function calls.
- Its behavior is better described under @code{free-translated-object}'s
- documentation.
- @subheading Examples
- @lisp
- CFFI-USER> (convert-to-foreign "a boat" :string)
- @result{} #<FOREIGN-ADDRESS #x097ACDC0>
- @result{} T
- CFFI-USER> (free-converted-object * :string t)
- @result{} NIL
- @end lisp
- @subheading See Also
- @seealso{convert-from-foreign} @*
- @seealso{convert-to-foreign} @*
- @seealso{free-translated-object}
- @c ===================================================================
- @c FREE-TRANSLATED-OBJECT
- @c TODO: update
- @page
- @node free-translated-object, translate-from-foreign, free-converted-object, Foreign Types
- @heading free-translated-object
- @subheading Syntax
- @GenericFunction{free-translated-object value type-name param}
- @subheading Arguments and Values
- @table @var
- @item pointer
- The foreign value returned by @code{translate-to-foreign}.
- @item type-name
- A symbol naming a foreign type defined by @code{defctype}.
- @item param
- The second value, if any, returned by @code{translate-to-foreign}.
- @end table
- @subheading Description
- This generic function may be specialized by user code to perform
- automatic deallocation of foreign objects as they are passed to C
- functions.
- Any methods defined on this generic function must EQL-specialize the
- @var{type-name} parameter on a symbol defined as a foreign type by
- the @code{defctype} macro.
- @subheading See Also
- @seealso{Foreign Type Translators} @*
- @seealso{translate-to-foreign}
- @c ===================================================================
- @c TRANSLATE-FROM-FOREIGN
- @c TODO: update
- @page
- @node translate-from-foreign, translate-to-foreign, free-translated-object, Foreign Types
- @heading translate-from-foreign
- @subheading Syntax
- @GenericFunction{translate-from-foreign foreign-value type-name @
- @res{} lisp-value}
- @subheading Arguments and Values
- @table @var
- @item foreign-value
- The foreign value to convert to a Lisp object.
- @item type-name
- A symbol naming a foreign type defined by @code{defctype}.
- @item lisp-value
- The lisp value to pass in place of @code{foreign-value} to Lisp code.
- @end table
- @subheading Description
- This generic function is invoked by @cffi{} to convert a foreign value to
- a Lisp value, such as when returning from a foreign function, passing
- arguments to a callback function, or accessing a foreign variable.
- To extend the @cffi{} type system by performing custom translations, this
- method may be specialized by @sc{eql}-specializing @code{type-name} on a
- symbol naming a foreign type defined with @code{defctype}. This
- method should return the appropriate Lisp value to use in place of the
- foreign value.
- The results are undefined if the @code{type-name} parameter is
- specialized in any way except an @sc{eql} specializer on a foreign type
- defined with @code{defctype}. Specifically, translations may not be
- defined for built-in types.
- @subheading See Also
- @seealso{Foreign Type Translators} @*
- @seealso{translate-to-foreign} @*
- @seealso{free-translated-object}
- @c ===================================================================
- @c TRANSLATE-TO-FOREIGN
- @c TODO: update
- @page
- @node translate-to-foreign, translate-into-foreign-memory, translate-from-foreign, Foreign Types
- @heading translate-to-foreign
- @subheading Syntax
- @GenericFunction{translate-to-foreign lisp-value type-name @
- @res{} foreign-value, alloc-param}
- @subheading Arguments and Values
- @table @var
- @item lisp-value
- The Lisp value to convert to foreign representation.
- @item type-name
- A symbol naming a foreign type defined by @code{defctype}.
- @item foreign-value
- The foreign value to pass in place of @code{lisp-value} to foreign code.
- @item alloc-param
- If present, this value will be passed to
- @code{free-translated-object}.
- @end table
- @subheading Description
- This generic function is invoked by @cffi{} to convert a Lisp value to a
- foreign value, such as when passing arguments to a foreign function,
- returning a value from a callback, or setting a foreign variable. A
- ``foreign value'' is one appropriate for passing to the next-lowest
- translator, including the low-level translators that are ultimately
- invoked invisibly with @cffi{}.
- To extend the @cffi{} type system by performing custom translations, this
- method may be specialized by @sc{eql}-specializing @code{type-name} on a
- symbol naming a foreign type defined with @code{defctype}. This
- method should return the appropriate foreign value to use in place of
- the Lisp value.
- In cases where @cffi{} can determine the lifetime of the foreign object
- returned by this method, it will invoke @code{free-translated-object}
- on the foreign object at the appropriate time. If
- @code{translate-to-foreign} returns a second value, it will be passed
- as the @code{param} argument to @code{free-translated-object}. This
- can be used to establish communication between the allocation and
- deallocation methods.
- The results are undefined if the @code{type-name} parameter is
- specialized in any way except an @sc{eql} specializer on a foreign type
- defined with @code{defctype}. Specifically, translations may not be
- defined for built-in types.
- @subheading See Also
- @seealso{Foreign Type Translators} @*
- @seealso{translate-from-foreign} @*
- @seealso{free-translated-object}
- @c ===================================================================
- @c TRANSLATE-INTO-FOREIGN-MEMORY
- @page
- @node translate-into-foreign-memory, with-foreign-slots, translate-to-foreign, Foreign Types
- @heading translate-into-foreign-memory
- @subheading Syntax
- @GenericFunction{translate-into-foreign-memory lisp-value type-name pointer}
- @subheading Arguments and Values
- @table @var
- @item lisp-value
- The Lisp value to convert to foreign representation.
- @item type-name
- A symbol or list @code{(:struct @var{structure-name})} naming a foreign type defined by @code{defctype}.
- @item pointer
- The foreign pointer where the translated object should be stored.
- @end table
- @subheading Description
- Translate the Lisp value into the foreign memory location given by
- pointer. The return value is not used.
- @c ===================================================================
- @c WITH-FOREIGN-SLOTS
- @page
- @node with-foreign-slots, , translate-into-foreign-memory, Foreign Types
- @heading with-foreign-slots
- @subheading Syntax
- @Macro{with-foreign-slots (vars ptr type) &body body}
- @subheading Arguments and Values
- @table @var
- @item vars
- A list with each element a symbol, or list of length two with the
- first element @code{:pointer} and the second a symbol.
- @item ptr
- A foreign pointer to a structure.
- @item type
- A structure type.
- @item body
- A list of forms to be executed.
- @end table
- @subheading Description
- The @code{with-foreign-slots} macro creates local symbol macros for each
- var in @var{vars} to reference foreign slots in @var{ptr} of @var{type}.
- If the var is a list starting with @code{:pointer}, it will bind the
- pointer to the slot (rather than the value). It is similar to Common
- Lisp's @code{with-slots} macro.
- @subheading Examples
- @lisp
- (defcstruct tm
- (sec :int)
- (min :int)
- (hour :int)
- (mday :int)
- (mon :int)
- (year :int)
- (wday :int)
- (yday :int)
- (isdst :boolean)
- (zone :string)
- (gmtoff :long))
- CFFI> (with-foreign-object (time :int)
- (setf (mem-ref time :int)
- (foreign-funcall "time" :pointer (null-pointer) :int))
- (foreign-funcall "gmtime" :pointer time (:pointer (:struct tm))))
- @result{} #<A Mac Pointer #x102A30>
- CFFI> (with-foreign-slots ((sec min hour mday mon year) * (:struct tm))
- (format nil "~A:~A:~A, ~A/~A/~A"
- hour min sec (+ 1900 year) mon mday))
- @result{} "7:22:47, 2005/8/2"
- @end lisp
- @subheading See Also
- @seealso{defcstruct} @*
- @seealso{defcunion} @*
- @seealso{foreign-slot-value}
- @c ===================================================================
- @c CHAPTER: Pointers
- @node Pointers, Strings, Foreign Types, Top
- @chapter Pointers
- All C data in @cffi{} is referenced through pointers. This includes
- defined C variables that hold immediate values, and integers.
- To see why this is, consider the case of the C integer. It is not
- only an arbitrary representation for an integer, congruent to Lisp's
- fixnums; the C integer has a specific bit pattern in memory defined by
- the C @acronym{ABI}. Lisp has no such constraint on its fixnums;
- therefore, it only makes sense to think of fixnums as C integers if
- you assume that @cffi{} converts them when necessary, such as when
- storing one for use in a C function call, or as the value of a C
- variable. This requires defining an area of memory@footnote{The
- definition of @dfn{memory} includes the @acronym{CPU} registers.},
- represented through an effective address, and storing it there.
- Due to this compartmentalization, it only makes sense to manipulate
- raw C data in Lisp through pointers to it. For example, while there
- may be a Lisp representation of a @code{struct} that is converted to C
- at store time, you may only manipulate its raw data through a pointer.
- The C compiler does this also, albeit informally.
- @menu
- * Basic Pointer Operations::
- * Allocating Foreign Memory::
- * Accessing Foreign Memory::
- Dictionary
- * foreign-free::
- * foreign-alloc::
- * foreign-symbol-pointer::
- * inc-pointer::
- * incf-pointer::
- * make-pointer::
- * mem-aptr::
- * mem-aref::
- * mem-ref::
- * null-pointer::
- * null-pointer-p::
- * pointerp::
- * pointer-address::
- * pointer-eq::
- * with-foreign-object::
- * with-foreign-objects::
- * with-foreign-pointer::
- @end menu
- @node Basic Pointer Operations, Allocating Foreign Memory, Pointers, Pointers
- @section Basic Pointer Operations
- Manipulating pointers proper can be accomplished through most of the
- other operations defined in the Pointers dictionary, such as
- @code{make-pointer}, @code{pointer-address}, and @code{pointer-eq}.
- When using them, keep in mind that they merely manipulate the Lisp
- representation of pointers, not the values they point to.
- @deftp {Lisp Type} foreign-pointer
- The pointers' representations differ from implementation to
- implementation and have different types. @code{foreign-pointer}
- provides a portable type alias to each of these types.
- @end deftp
- @node Allocating Foreign Memory, Accessing Foreign Memory, Basic Pointer Operations, Pointers
- @section Allocating Foreign Memory
- @cffi{} provides support for stack and heap C memory allocation.
- Stack allocation, done with @code{with-foreign-object}, is sometimes
- called ``dynamic'' allocation in Lisp, because memory allocated as
- such has dynamic extent, much as with @code{let} bindings of special
- variables.
- This should not be confused with what C calls ``dynamic'' allocation,
- or that done with @code{malloc} and friends. This sort of heap
- allocation is done with @code{foreign-alloc}, creating objects that
- exist until freed with @code{foreign-free}.
- @node Accessing Foreign Memory, foreign-free, Allocating Foreign Memory, Pointers
- @section Accessing Foreign Memory
- When manipulating raw C data, consider that all pointers are pointing
- to an array. When you only want one C value, such as a single
- @code{struct}, this array only has one such value. It is worthwhile
- to remember that everything is an array, though, because this is also
- the semantic that C imposes natively.
- C values are accessed as the @code{setf}-able places defined by
- @code{mem-aref} and @code{mem-ref}. Given a pointer and a @cffi{}
- type (@pxref{Foreign Types}), either of these will dereference the
- pointer, translate the C data there back to Lisp, and return the
- result of said translation, performing the reverse operation when
- @code{setf}-ing. To decide which one to use, consider whether you
- would use the array index operator @code{[@var{n}]} or the pointer
- dereference @code{*} in C; use @code{mem-aref} for array indexing and
- @code{mem-ref} for pointer dereferencing.
- @c ===================================================================
- @c FOREIGN-FREE
- @page
- @node foreign-free, foreign-alloc, Accessing Foreign Memory, Pointers
- @heading foreign-free
- @subheading Syntax
- @Function{foreign-free ptr @res{} undefined}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A foreign pointer.
- @end table
- @subheading Description
- The @code{foreign-free} function frees a @code{ptr} previously
- allocated by @code{foreign-alloc}. The consequences of freeing a given
- pointer twice are undefined.
- @subheading Examples
- @lisp
- CFFI> (foreign-alloc :int)
- @result{} #<A Mac Pointer #x1022E0>
- CFFI> (foreign-free *)
- @result{} NIL
- @end lisp
- @subheading See Also
- @seealso{foreign-alloc} @*
- @seealso{with-foreign-pointer}
- @c ===================================================================
- @c FOREIGN-ALLOC
- @page
- @node foreign-alloc, foreign-symbol-pointer, foreign-free, Pointers
- @heading foreign-alloc
- @subheading Syntax
- @Function{foreign-alloc type &key initial-element initial-contents (count 1) @
- null-terminated-p @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item type
- A foreign type.
- @item initial-element
- A Lisp object.
- @item initial-contents
- A sequence.
- @item count
- An integer. Defaults to 1 or the length of @var{initial-contents} if
- supplied.
- @item null-terminated-p
- A boolean, false by default.
- @item pointer
- A foreign pointer to the newly allocated memory.
- @end table
- @subheading Description
- The @code{foreign-alloc} function allocates enough memory to hold
- @var{count} objects of type @var{type} and returns a
- @var{pointer}. This memory must be explicitly freed using
- @code{foreign-free} once it is no longer needed.
- If @var{initial-element} is supplied, it is used to initialize the
- @var{count} objects the newly allocated memory holds.
- If an @var{initial-contents} sequence is supplied, it must have a
- length less than or equal to @var{count} and each of its elements
- will be used to initialize the contents of the newly allocated
- memory.
- If @var{count} is omitted and @var{initial-contents} is specified, it
- will default to @code{(length @var{initial-contents})}.
- @var{initial-element} and @var{initial-contents} are mutually
- exclusive.
- When @var{null-terminated-p} is true,
- @code{(1+ (max @var{count} (length @var{initial-contents})))} elements
- are allocated and the last one is set to @code{NULL}. Note that in
- this case @var{type} must be a pointer type (ie. a type that
- canonicalizes to @code{:pointer}), otherwise an error is signaled.
- @subheading Examples
- @lisp
- CFFI> (foreign-alloc :char)
- @result{} #<A Mac Pointer #x102D80> ; @lispcmt{A pointer to 1 byte of memory.}
- CFFI> (foreign-alloc :char :count 20)
- @result{} #<A Mac Pointer #x1024A0> ; @lispcmt{A pointer to 20 bytes of memory.}
- CFFI> (foreign-alloc :int :initial-element 12)
- @result{} #<A Mac Pointer #x1028B0>
- CFFI> (mem-ref * :int)
- @result{} 12
- CFFI> (foreign-alloc :int :initial-contents '(1 2 3))
- @result{} #<A Mac Pointer #x102950>
- CFFI> (loop for i from 0 below 3
- collect (mem-aref * :int i))
- @result{} (1 2 3)
- CFFI> (foreign-alloc :int :initial-contents #(1 2 3))
- @result{} #<A Mac Pointer #x102960>
- CFFI> (loop for i from 0 below 3
- collect (mem-aref * :int i))
- @result{} (1 2 3)
- ;;; @lispcmt{Allocate a char** pointer that points to newly allocated memory}
- ;;; @lispcmt{by the :string type translator for the string "foo".}
- CFFI> (foreign-alloc :string :initial-element "foo")
- @result{} #<A Mac Pointer #x102C40>
- @end lisp
- @lisp
- ;;; @lispcmt{Allocate a null-terminated array of strings.}
- ;;; @lispcmt{(Note: FOREIGN-STRING-TO-LISP returns NIL when passed a null pointer)}
- CFFI> (foreign-alloc :string
- :initial-contents '("foo" "bar" "baz")
- :null-terminated-p t)
- @result{} #<A Mac Pointer #x102D20>
- CFFI> (loop for i from 0 below 4
- collect (mem-aref * :string i))
- @result{} ("foo" "bar" "baz" NIL)
- CFFI> (progn
- (dotimes (i 3)
- (foreign-free (mem-aref ** :pointer i)))
- (foreign-free **))
- @result{} nil
- @end lisp
- @subheading See Also
- @seealso{foreign-free} @*
- @seealso{with-foreign-object} @*
- @seealso{with-foreign-pointer}
- @c ===================================================================
- @c FOREIGN-SYMBOL-POINTER
- @page
- @node foreign-symbol-pointer, inc-pointer, foreign-alloc, Pointers
- @heading foreign-symbol-pointer
- @subheading Syntax
- @Function{foreign-symbol-pointer foreign-name &key library @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item foreign-name
- A string.
- @item pointer
- A foreign pointer, or @code{nil}.
- @item library
- A Lisp symbol or an instance of @code{foreign-library}.
- @end table
- @subheading Description
- The function @code{foreign-symbol-pointer} will return a foreign
- pointer corresponding to the foreign symbol denoted by the string
- @var{foreign-name}. If a foreign symbol named @var{foreign-name}
- doesn't exist, @code{nil} is returned.
- ABI name manglings will be performed on @var{foreign-name} by
- @code{foreign-symbol-pointer} if necessary. (eg: adding a leading
- underscore on darwin/ppc)
- @var{library} should name a foreign library as defined by
- @code{define-foreign-library}, @code{:default} (which is the default)
- or an instance of @code{foreign-library} as returned by
- @code{load-foreign-library}.
- @strong{Important note:} do not keep these pointers across saved Lisp
- cores as the foreign-library may move across sessions.
- @subheading Examples
- @lisp
- CFFI> (foreign-symbol-pointer "errno")
- @result{} #<A Mac Pointer #xA0008130>
- CFFI> (foreign-symbol-pointer "strerror")
- @result{} #<A Mac Pointer #x9002D0F8>
- CFFI> (foreign-funcall-pointer * () :int (mem-ref ** :int) :string)
- @result{} "No such file or directory"
- CFFI> (foreign-symbol-pointer "inexistent symbol")
- @result{} NIL
- @end lisp
- @subheading See Also
- @seealso{defcvar}
- @c ===================================================================
- @c INC-POINTER
- @page
- @node inc-pointer, incf-pointer, foreign-symbol-pointer, Pointers
- @heading inc-pointer
- @subheading Syntax
- @Function{inc-pointer pointer offset @res{} new-pointer}
- @subheading Arguments and Values
- @table @var
- @item pointer
- @itemx new-pointer
- A foreign pointer.
- @item offset
- An integer.
- @end table
- @subheading Description
- The function @code{inc-pointer} will return a @var{new-pointer} pointing
- @var{offset} bytes past @var{pointer}.
- @subheading Examples
- @lisp
- CFFI> (foreign-string-alloc "Common Lisp")
- @result{} #<A Mac Pointer #x102EA0>
- CFFI> (inc-pointer * 7)
- @result{} #<A Mac Pointer #x102EA7>
- CFFI> (foreign-string-to-lisp *)
- @result{} "Lisp"
- @end lisp
- @subheading See Also
- @seealso{incf-pointer} @*
- @seealso{make-pointer} @*
- @seealso{pointerp} @*
- @seealso{null-pointer} @*
- @seealso{null-pointer-p}
- @c ===================================================================
- @c INCF-POINTER
- @page
- @node incf-pointer, make-pointer, inc-pointer, Pointers
- @heading incf-pointer
- @subheading Syntax
- @Macro{incf-pointer place &optional (offset 1) @res{} new-pointer}
- @subheading Arguments and Values
- @table @var
- @item place
- A @code{setf} place.
- @item new-pointer
- A foreign pointer.
- @item offset
- An integer.
- @end table
- @subheading Description
- The @code{incf-pointer} macro takes the foreign pointer from
- @var{place} and creates a @var{new-pointer} incremented by
- @var{offset} bytes and which is stored in @var{place}.
- @subheading Examples
- @lisp
- CFFI> (defparameter *two-words* (foreign-string-alloc "Common Lisp"))
- @result{} *TWO-WORDS*
- CFFI> (defparameter *one-word* *two-words*)
- @result{} *ONE-WORD*
- CFFI> (incf-pointer *one-word* 7)
- @result{} #.(SB-SYS:INT-SAP #X00600457)
- CFFI> (foreign-string-to-lisp *one-word*)
- @result{} "Lisp"
- CFFI> (foreign-string-to-lisp *two-words*)
- @result{} "Common Lisp"
- @end lisp
- @subheading See Also
- @seealso{inc-pointer} @*
- @seealso{make-pointer} @*
- @seealso{pointerp} @*
- @seealso{null-pointer} @*
- @seealso{null-pointer-p}
- @c ===================================================================
- @c MAKE-POINTER
- @page
- @node make-pointer, mem-aptr, incf-pointer, Pointers
- @heading make-pointer
- @subheading Syntax
- @Function{make-pointer address @res{} ptr}
- @subheading Arguments and Values
- @table @var
- @item address
- An integer.
- @item ptr
- A foreign pointer.
- @end table
- @subheading Description
- The function @code{make-pointer} will return a foreign pointer
- pointing to @var{address}.
- @subheading Examples
- @lisp
- CFFI> (make-pointer 42)
- @result{} #<FOREIGN-ADDRESS #x0000002A>
- CFFI> (pointerp *)
- @result{} T
- CFFI> (pointer-address **)
- @result{} 42
- CFFI> (inc-pointer *** -42)
- @result{} #<FOREIGN-ADDRESS #x00000000>
- CFFI> (null-pointer-p *)
- @result{} T
- CFFI> (typep ** 'foreign-pointer)
- @result{} T
- @end lisp
- @subheading See Also
- @seealso{inc-pointer} @*
- @seealso{null-pointer} @*
- @seealso{null-pointer-p} @*
- @seealso{pointerp} @*
- @seealso{pointer-address} @*
- @seealso{pointer-eq} @*
- @seealso{mem-ref}
- @c ===================================================================
- @c MEM-APTR
- @page
- @node mem-aptr, mem-aref, make-pointer, Pointers
- @heading mem-aptr
- @subheading Syntax
- @Accessor{mem-aptr ptr type &optional (index 0)}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A foreign pointer.
- @item type
- A foreign type.
- @item index
- An integer.
- @item new-value
- A Lisp value compatible with @var{type}.
- @end table
- @subheading Description
- The @code{mem-aptr} function finds the pointer to an element of the array.
- @lisp
- (mem-aptr ptr type n)
- ;; @lispcmt{is identical to:}
- (inc-pointer ptr (* n (foreign-type-size type)))
- @end lisp
- @subheading Examples
- @lisp
- CFFI> (with-foreign-string (str "Hello, foreign world!")
- (mem-aptr str :char 6))
- @result{} #.(SB-SYS:INT-SAP #X0063D4B6)
- @end lisp
- @c ===================================================================
- @c MEM-AREF
- @page
- @node mem-aref, mem-ref, mem-aptr, Pointers
- @heading mem-aref
- @subheading Syntax
- @Accessor{mem-aref ptr type &optional (index 0)}
- (setf (@strong{mem-aref} @emph{ptr type &optional (index 0)) new-value})
- @subheading Arguments and Values
- @table @var
- @item ptr
- A foreign pointer.
- @item type
- A foreign type.
- @item index
- An integer.
- @item new-value
- A Lisp value compatible with @var{type}.
- @end table
- @subheading Description
- The @code{mem-aref} function is similar to @code{mem-ref} but will
- automatically calculate the offset from an @var{index}.
- @lisp
- (mem-aref ptr type n)
- ;; @lispcmt{is identical to:}
- (mem-ref ptr type (* n (foreign-type-size type)))
- @end lisp
- @subheading Examples
- @lisp
- CFFI> (with-foreign-string (str "Hello, foreign world!")
- (mem-aref str :char 6))
- @result{} 32
- CFFI> (code-char *)
- @result{} #\Space
- CFFI> (with-foreign-object (array :int 10)
- (loop for i below 10
- do (setf (mem-aref array :int i) (random 100)))
- (loop for i below 10 collect (mem-aref array :int i)))
- @result{} (22 7 22 52 69 1 46 93 90 65)
- @end lisp
- @subheading Compatibility Note
- For compatibility with older versions of CFFI, @ref{mem-aref} will
- produce a pointer for the deprecated bare structure specification, but
- it is consistent with other types for the current specification form
- @code{(:struct @var{structure-name})} and provides a Lisp object
- translated from the structure (by default a plist). In order to obtain
- the pointer, you should use the new function @ref{mem-aptr}.
- @subheading See Also
- @seealso{mem-ref} @*
- @seealso{mem-aptr}
- @c ===================================================================
- @c MEM-REF
- @page
- @node mem-ref, null-pointer, mem-aref, Pointers
- @heading mem-ref
- @subheading Syntax
- @Accessor{mem-ref ptr type &optional offset @res{} object}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A pointer.
- @item type
- A foreign type.
- @item offset
- An integer (in byte units).
- @item object
- The value @var{ptr} points to.
- @end table
- @subheading Description
- @subheading Examples
- @lisp
- CFFI> (with-foreign-string (ptr "Saluton")
- (setf (mem-ref ptr :char 3) (char-code #\a))
- (loop for i from 0 below 8
- collect (code-char (mem-ref ptr :char i))))
- @result{} (#\S #\a #\l #\a #\t #\o #\n #\Null)
- CFFI> (setq ptr-to-int (foreign-alloc :int))
- @result{} #<A Mac Pointer #x1047D0>
- CFFI> (mem-ref ptr-to-int :int)
- @result{} 1054619
- CFFI> (setf (mem-ref ptr-to-int :int) 1984)
- @result{} 1984
- CFFI> (mem-ref ptr-to-int :int)
- @result{} 1984
- @end lisp
- @subheading See Also
- @seealso{mem-aref}
- @c ===================================================================
- @c NULL-POINTER
- @page
- @node null-pointer, null-pointer-p, mem-ref, Pointers
- @heading null-pointer
- @subheading Syntax
- @Function{null-pointer @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item pointer
- A @code{NULL} pointer.
- @end table
- @subheading Description
- The function @code{null-pointer} returns a null pointer.
- @subheading Examples
- @lisp
- CFFI> (null-pointer)
- @result{} #<A Null Mac Pointer>
- CFFI> (pointerp *)
- @result{} T
- @end lisp
- @subheading See Also
- @seealso{null-pointer-p} @*
- @seealso{make-pointer}
- @c ===================================================================
- @c NULL-POINTER-P
- @page
- @node null-pointer-p, pointerp, null-pointer, Pointers
- @heading null-pointer-p
- @subheading Syntax
- @Function{null-pointer-p ptr @res{} boolean}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A foreign pointer that may be a null pointer.
- @item boolean
- @code{T} or @code{NIL}.
- @end table
- @subheading Description
- The function @code{null-pointer-p} returns true if @var{ptr} is a null
- pointer and false otherwise.
- @subheading Examples
- @lisp
- CFFI> (null-pointer-p (null-pointer))
- @result{} T
- @end lisp
- @lisp
- (defun contains-str-p (big little)
- (not (null-pointer-p
- (foreign-funcall "strstr" :string big :string little :pointer))))
- CFFI> (contains-str-p "Popcorns" "corn")
- @result{} T
- CFFI> (contains-str-p "Popcorns" "salt")
- @result{} NIL
- @end lisp
- @subheading See Also
- @seealso{null-pointer} @*
- @seealso{pointerp}
- @c ===================================================================
- @c POINTERP
- @page
- @node pointerp, pointer-address, null-pointer-p, Pointers
- @heading pointerp
- @subheading Syntax
- @Function{pointerp ptr @res{} boolean}
- @subheading Arguments and Values
- @table @var
- @item ptr
- An object that may be a foreign pointer.
- @item boolean
- @code{T} or @code{NIL}.
- @end table
- @subheading Description
- The function @code{pointerp} returns true if @var{ptr} is a foreign
- pointer and false otherwise.
- @subheading Implementation-specific Notes
- In Allegro CL, foreign pointers are integers thus in this
- implementation @code{pointerp} will return true for any ordinary integer.
- @subheading Examples
- @lisp
- CFFI> (foreign-alloc 32)
- @result{} #<A Mac Pointer #x102D20>
- CFFI> (pointerp *)
- @result{} T
- CFFI> (pointerp "this is not a pointer")
- @result{} NIL
- @end lisp
- @subheading See Also
- @seealso{make-pointer}
- @seealso{null-pointer-p}
- @c ===================================================================
- @c POINTER-ADDRESS
- @page
- @node pointer-address, pointer-eq, pointerp, Pointers
- @heading pointer-address
- @subheading Syntax
- @Function{pointer-address ptr @res{} address}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A foreign pointer.
- @item address
- An integer.
- @end table
- @subheading Description
- The function @code{pointer-address} will return the @var{address} of
- a foreign pointer @var{ptr}.
- @subheading Examples
- @lisp
- CFFI> (pointer-address (null-pointer))
- @result{} 0
- CFFI> (pointer-address (make-pointer 123))
- @result{} 123
- @end lisp
- @subheading See Also
- @seealso{make-pointer} @*
- @seealso{inc-pointer} @*
- @seealso{null-pointer} @*
- @seealso{null-pointer-p} @*
- @seealso{pointerp} @*
- @seealso{pointer-eq} @*
- @seealso{mem-ref}
- @c ===================================================================
- @c POINTER-EQ
- @page
- @node pointer-eq, with-foreign-object, pointer-address, Pointers
- @heading pointer-eq
- @subheading Syntax
- @Function{pointer-eq ptr1 ptr2 @res{} boolean}
- @subheading Arguments and Values
- @table @var
- @item ptr1
- @itemx ptr2
- A foreign pointer.
- @item boolean
- @code{T} or @code{NIL}.
- @end table
- @subheading Description
- The function @code{pointer-eq} returns true if @var{ptr1} and
- @var{ptr2} point to the same memory address and false otherwise.
- @subheading Implementation-specific Notes
- The representation of foreign pointers varies across the various Lisp
- implementations as does the behaviour of the built-in Common Lisp
- equality predicates. Comparing two pointers that point to the same
- address with @code{EQ} Lisps will return true on some Lisps, others require
- more general predicates like @code{EQL} or @code{EQUALP} and finally
- some will return false using any of these predicates. Therefore, for
- portability, you should use @code{POINTER-EQ}.
- @subheading Examples
- This is an example using @acronym{SBCL}, see the
- implementation-specific notes above.
- @lisp
- CFFI> (eql (null-pointer) (null-pointer))
- @result{} NIL
- CFFI> (pointer-eq (null-pointer) (null-pointer))
- @result{} T
- @end lisp
- @subheading See Also
- @seealso{inc-pointer}
- @c ===================================================================
- @c WITH-FOREIGN-OBJECT
- @page
- @node with-foreign-object, with-foreign-pointer, pointer-eq, Pointers
- @heading with-foreign-object, with-foreign-objects
- @subheading Syntax
- @Macro{with-foreign-object (var type &optional count) &body body}
- @anchor{with-foreign-objects}
- @Macro{with-foreign-objects (bindings) &body body}
- bindings ::= @{(var type &optional count)@}* @*
- @subheading Arguments and Values
- @table @var
- @item var
- A symbol.
- @item type
- A foreign type, evaluated.
- @item count
- An integer.
- @end table
- @subheading Description
- The macros @code{with-foreign-object} and @code{with-foreign-objects}
- bind @var{var} to a pointer to @var{count} newly allocated objects
- of type @var{type} during @var{body}. The buffer has dynamic extent
- and may be stack allocated if supported by the host Lisp.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-object (array :int 10)
- (dotimes (i 10)
- (setf (mem-aref array :int i) (random 100)))
- (loop for i below 10
- collect (mem-aref array :int i)))
- @result{} (22 7 22 52 69 1 46 93 90 65)
- @end lisp
- @subheading See Also
- @seealso{foreign-alloc}
- @c ===================================================================
- @c WITH-FOREIGN-POINTER
- @page
- @node with-foreign-pointer, , with-foreign-object, Pointers
- @heading with-foreign-pointer
- @subheading Syntax
- @Macro{with-foreign-pointer (var size &optional size-var) &body body}
- @subheading Arguments and Values
- @table @var
- @item var
- @itemx size-var
- A symbol.
- @item size
- An integer.
- @item body
- A list of forms to be executed.
- @end table
- @subheading Description
- The @code{with-foreign-pointer} macro, binds @var{var} to @var{size}
- bytes of foreign memory during @var{body}. The pointer in @var{var}
- is invalid beyond the dynamic extend of @var{body} and may be
- stack-allocated if supported by the implementation.
- If @var{size-var} is supplied, it will be bound to @var{size} during
- @var{body}.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-pointer (string 4 size)
- (setf (mem-ref string :char (1- size)) 0)
- (lisp-string-to-foreign "Popcorns" string size)
- (loop for i from 0 below size
- collect (code-char (mem-ref string :char i))))
- @result{} (#\P #\o #\p #\Null)
- @end lisp
- @subheading See Also
- @seealso{foreign-alloc} @*
- @seealso{foreign-free}
- @c ===================================================================
- @c CHAPTER: Strings
- @node Strings, Variables, Pointers, Top
- @chapter Strings
- As with many languages, Lisp and C have special support for logical
- arrays of characters, going so far as to give them a special name,
- ``strings''. In that spirit, @cffi{} provides special support for
- translating between Lisp and C strings.
- The @code{:string} type and the symbols related below also serve as an
- example of what you can do portably with @cffi{}; were it not
- included, you could write an equally functional @file{strings.lisp}
- without referring to any implementation-specific symbols.
- @menu
- Dictionary
- * *default-foreign-encoding*::
- * foreign-string-alloc::
- * foreign-string-free::
- * foreign-string-to-lisp::
- * lisp-string-to-foreign::
- * with-foreign-string::
- * with-foreign-strings::
- * with-foreign-pointer-as-string::
- @end menu
- @c ===================================================================
- @c *DEFAULT-FOREIGN-ENCODING*
- @page
- @node *default-foreign-encoding*, foreign-string-alloc, Strings, Strings
- @heading *default-foreign-encoding*
- @subheading Syntax
- @Variable{*default-foreign-encoding*}
- @subheading Value type
- A keyword.
- @subheading Initial value
- @code{:utf-8}
- @subheading Description
- This special variable holds the default foreign encoding.
- @subheading Examples
- @lisp
- CFFI> *default-foreign-encoding*
- :utf-8
- CFFI> (foreign-funcall "strdup" (:string :encoding :utf-16) "foo" :string)
- "f"
- CFFI> (let ((*default-foreign-encoding* :utf-16))
- (foreign-funcall "strdup" (:string :encoding :utf-16) "foo" :string))
- "foo"
- @end lisp
- @subheading See also
- @seealso{Other Types} (@code{:string} type) @*
- @seealso{foreign-string-alloc} @*
- @seealso{foreign-string-to-lisp} @*
- @seealso{lisp-string-to-foreign} @*
- @seealso{with-foreign-string} @*
- @seealso{with-foreign-pointer-as-string}
- @c ===================================================================
- @c FOREIGN-STRING-ALLOC
- @page
- @node foreign-string-alloc, foreign-string-free, *default-foreign-encoding*, Strings
- @heading foreign-string-alloc
- @subheading Syntax
- @Function{foreign-string-alloc string &key encoding null-terminated-p @
- start end @res{} pointer}
- @subheading Arguments and Values
- @table @emph
- @item @var{string}
- A Lisp string.
- @item @var{encoding}
- Foreign encoding. Defaults to @code{*default-foreign-encoding*}.
- @item @var{null-terminated-p}
- Boolean, defaults to true.
- @item @var{start}, @var{end}
- Bounding index designators of @var{string}. 0 and @code{nil}, by
- default.
- @item @var{pointer}
- A pointer to the newly allocated foreign string.
- @end table
- @subheading Description
- The @code{foreign-string-alloc} function allocates foreign memory
- holding a copy of @var{string} converted using the specified
- @var{encoding}. @var{Start} specifies an offset into @var{string} and
- @var{end} marks the position following the last element of the foreign
- string.
- This string must be freed with @code{foreign-string-free}.
- If @var{null-terminated-p} is false, the string will not be
- null-terminated.
- @subheading Examples
- @lisp
- CFFI> (defparameter *str* (foreign-string-alloc "Hello, foreign world!"))
- @result{} #<FOREIGN-ADDRESS #x00400560>
- CFFI> (foreign-funcall "strlen" :pointer *str* :int)
- @result{} 21
- @end lisp
- @subheading See Also
- @seealso{foreign-string-free} @*
- @seealso{with-foreign-string}
- @c @seealso{:string}
- @c ===================================================================
- @c FOREIGN-STRING-FREE
- @page
- @node foreign-string-free, foreign-string-to-lisp, foreign-string-alloc, Strings
- @heading foreign-string-free
- @subheading Syntax
- @Function{foreign-string-free pointer}
- @subheading Arguments and Values
- @table @var
- @item pointer
- A pointer to a string allocated by @code{foreign-string-alloc}.
- @end table
- @subheading Description
- The @code{foreign-string-free} function frees a foreign string
- allocated by @code{foreign-string-alloc}.
- @subheading Examples
- @subheading See Also
- @seealso{foreign-string-alloc}
- @c ===================================================================
- @c FOREIGN-STRING-TO-LISP
- @page
- @node foreign-string-to-lisp, lisp-string-to-foreign, foreign-string-free, Strings
- @heading foreign-string-to-lisp
- @subheading Syntax
- @Function{foreign-string-to-lisp ptr &key offset count max-chars @
- encoding @res{} string}
- @subheading Arguments and Values
- @table @var
- @item ptr
- A pointer.
- @item offset
- An integer greater than or equal to 0. Defauls to 0.
- @item count
- Either @code{nil} (the default), or an integer greater than or equal to 0.
- @item max-chars
- An integer greater than or equal to 0.
- @code{(1- array-total-size-limit)}, by default.
- @item encoding
- Foreign encoding. Defaults to @code{*default-foreign-encoding*}.
- @item string
- A Lisp string.
- @end table
- @subheading Description
- The @code{foreign-string-to-lisp} function converts at most
- @var{count} octets from @var{ptr} into a Lisp string, using the
- defined @var{encoding}.
- If @var{count} is @code{nil} (the default), characters are copied
- until @var{max-chars} is reached or a @code{NULL} character is found.
- If @var{ptr} is a null pointer, returns @code{nil}.
- Note that the @code{:string} type will automatically convert between
- Lisp strings and foreign strings.
- @subheading Examples
- @lisp
- CFFI> (foreign-funcall "getenv" :string "HOME" :pointer)
- @result{} #<FOREIGN-ADDRESS #xBFFFFFD5>
- CFFI> (foreign-string-to-lisp *)
- @result{} "/Users/luis"
- @end lisp
- @subheading See Also
- @seealso{lisp-string-to-foreign} @*
- @seealso{foreign-string-alloc}
- @c @seealso{:string}
- @c ===================================================================
- @c LISP-STRING-TO-FOREIGN
- @page
- @node lisp-string-to-foreign, with-foreign-string, foreign-string-to-lisp, Strings
- @heading lisp-string-to-foreign
- @subheading Syntax
- @Function{lisp-string-to-foreign string buffer bufsize &key start @
- end offset encoding @res{} buffer}
- @subheading Arguments and Values
- @table @emph
- @item @var{string}
- A Lisp string.
- @item @var{buffer}
- A foreign pointer.
- @item @var{bufsize}
- An integer.
- @item @var{start}, @var{end}
- Bounding index designators of @var{string}. 0 and @code{nil}, by
- default.
- @item @var{offset}
- An integer greater than or equal to 0. Defauls to 0.
- @item @var{encoding}
- Foreign encoding. Defaults to @code{*default-foreign-encoding*}.
- @end table
- @subheading Description
- The @code{lisp-string-to-foreign} function copies at most
- @var{bufsize}-1 octets from a Lisp @var{string} using the specified
- @var{encoding} into @var{buffer}+@var{offset}. The foreign string will
- be null-terminated.
- @var{Start} specifies an offset into @var{string} and
- @var{end} marks the position following the last element of the foreign
- string.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-pointer-as-string (str 255)
- (lisp-string-to-foreign "Hello, foreign world!" str 6))
- @result{} "Hello"
- @end lisp
- @subheading See Also
- @seealso{foreign-string-alloc} @*
- @seealso{foreign-string-to-lisp} @*
- @seealso{with-foreign-pointer-as-string}
- @c ===================================================================
- @c WITH-FOREIGN-STRING
- @page
- @node with-foreign-string, with-foreign-pointer-as-string, lisp-string-to-foreign, Strings
- @heading with-foreign-string, with-foreign-strings
- @subheading Syntax
- @Macro{with-foreign-string (var-or-vars string &rest args) &body body}
- @anchor{with-foreign-strings}
- @Macro{with-foreign-strings (bindings) &body body}
- var-or-vars ::= var | (var &optional octet-size-var) @*
- bindings ::= @{(var-or-vars string &rest args)@}*
- @subheading Arguments and Values
- @table @emph
- @item @var{var}, @var{byte-size-var}
- A symbol.
- @item @var{string}
- A Lisp string.
- @item @var{body}
- A list of forms to be executed.
- @end table
- @subheading Description
- The @code{with-foreign-string} macro will bind @var{var} to a newly
- allocated foreign string containing @var{string}. @var{Args} is passed
- to the underlying @code{foreign-string-alloc} call.
- If @var{octet-size-var} is provided, it will be bound the length of
- foreign string in octets including the null terminator.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-string (foo "12345")
- (foreign-funcall "strlen" :pointer foo :int))
- @result{} 5
- @end lisp
- @subheading See Also
- @seealso{foreign-string-alloc} @*
- @seealso{with-foreign-pointer-as-string}
- @c ===================================================================
- @c WITH-FOREIGN-POINTER-AS-STRING
- @page
- @node with-foreign-pointer-as-string, , with-foreign-string, Strings
- @heading with-foreign-pointer-as-string
- @subheading Syntax
- @Macro{with-foreign-pointer-as-string (var size &optional size-var @
- &rest args) &body body @res{} string}
- @subheading Arguments and Values
- @table @var
- @item var
- A symbol.
- @item string
- A Lisp string.
- @item body
- List of forms to be executed.
- @end table
- @subheading Description
- The @code{with-foreign-pointer-as-string} macro is similar to
- @code{with-foreign-pointer} except that @var{var} is used as the
- returned value of an implicit @code{progn} around @var{body}, after
- being converted to a Lisp string using the provided @var{args}.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-pointer-as-string (str 6 str-size :encoding :ascii)
- (lisp-string-to-foreign "Hello, foreign world!" str str-size))
- @result{} "Hello"
- @end lisp
- @subheading See Also
- @seealso{foreign-string-alloc} @*
- @seealso{with-foreign-string}
- @c ===================================================================
- @c CHAPTER: Variables
- @node Variables, Functions, Strings, Top
- @chapter Variables
- @menu
- Dictionary
- * defcvar::
- * get-var-pointer::
- @end menu
- @c ===================================================================
- @c DEFCVAR
- @page
- @node defcvar, get-var-pointer, Variables, Variables
- @heading defcvar
- @subheading Syntax
- @Macro{defcvar name-and-options type &optional documentation @res{} lisp-name}
- @var{name-and-options} ::= name | (name &key read-only (library :default)) @*
- @var{name} ::= lisp-name [foreign-name] | foreign-name [lisp-name] @*
- @subheading Arguments and Values
- @table @var
- @item foreign-name
- A string denoting a foreign function.
- @item lisp-name
- A symbol naming the Lisp function to be created.
- @item type
- A foreign type.
- @item read-only
- A boolean.
- @item documentation
- A Lisp string; not evaluated.
- @end table
- @subheading Description
- The @code{defcvar} macro defines a symbol macro @var{lisp-name} that looks
- up @var{foreign-name} and dereferences it acording to @var{type}. It
- can also be @code{setf}ed, unless @var{read-only} is true, in which
- case an error will be signaled.
- When one of @var{lisp-name} or @var{foreign-name} is omitted, the
- other is automatically derived using the following rules:
- @itemize
- @item
- Foreign names are converted to Lisp names by uppercasing, replacing
- underscores with hyphens, and wrapping around asterisks.
- @item
- Lisp names are converted to foreign names by lowercasing, replacing
- hyphens with underscores, and removing asterisks, if any.
- @end itemize
- @subheading Examples
- @lisp
- CFFI> (defcvar "errno" :int)
- @result{} *ERRNO*
- CFFI> (foreign-funcall "strerror" :int *errno* :string)
- @result{} "Inappropriate ioctl for device"
- CFFI> (setf *errno* 1)
- @result{} 1
- CFFI> (foreign-funcall "strerror" :int *errno* :string)
- @result{} "Operation not permitted"
- @end lisp
- Trying to modify a read-only foreign variable:
- @lisp
- CFFI> (defcvar ("errno" +error-number+ :read-only t) :int)
- @result{} +ERROR-NUMBER+
- CFFI> (setf +error-number+ 12)
- ;; @lispcmt{@error{} Trying to modify read-only foreign var: +ERROR-NUMBER+.}
- @end lisp
- @emph{Note that accessing @code{errno} this way won't work with every
- implementation of the C standard library.}
- @subheading See Also
- @seealso{get-var-pointer}
- @c ===================================================================
- @c GET-VAR-POINTER
- @page
- @node get-var-pointer, , defcvar, Variables
- @heading get-var-pointer
- @subheading Syntax
- @Function{get-var-pointer symbol @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item symbol
- A symbol denoting a foreign variable defined with @code{defcvar}.
- @item pointer
- A foreign pointer.
- @end table
- @subheading Description
- The function @code{get-var-pointer} will return a @var{pointer} to the
- foreign global variable @var{symbol} previously defined with
- @code{defcvar}.
- @subheading Examples
- @lisp
- CFFI> (defcvar "errno" :int :read-only t)
- @result{} *ERRNO*
- CFFI> *errno*
- @result{} 25
- CFFI> (get-var-pointer '*errno*)
- @result{} #<A Mac Pointer #xA0008130>
- CFFI> (mem-ref * :int)
- @result{} 25
- @end lisp
- @subheading See Also
- @seealso{defcvar}
- @c ===================================================================
- @c CHAPTER: Functions
- @node Functions, Libraries, Variables, Top
- @chapter Functions
- @menu
- @c * Defining Foreign Functions::
- @c * Calling Foreign Functions::
- Dictionary
- * defcfun::
- * foreign-funcall::
- * foreign-funcall-pointer::
- * foreign-funcall-varargs::
- * foreign-funcall-pointer-varargs::
- * translate-camelcase-name::
- * translate-name-from-foreign::
- * translate-name-to-foreign::
- * translate-underscore-separated-name::
- @end menu
- @c @node Calling Foreign Functions
- @c @section Calling Foreign Functions
- @c @node Defining Foreign Functions
- @c @section Defining Foreign Functions
- @c ===================================================================
- @c DEFCFUN
- @page
- @node defcfun, foreign-funcall, Functions, Functions
- @heading defcfun
- @subheading Syntax
- @Macro{defcfun name-and-options return-type &body [docstring] arguments [&rest] @
- @res{} lisp-name}
- @var{name-and-options} ::= @var{name} | (@var{name} &key @var{library} @var{convention}) @*
- @var{name} ::= @var{lisp-name} [@var{foreign-name}] | @var{foreign-name} [@var{lisp-name}] @*
- @var{arguments} ::= @{ (@var{arg-name} @var{arg-type}) @}* @*
- @subheading Arguments and Values
- @table @var
- @item foreign-name
- A string denoting a foreign function.
- @item lisp-name
- A symbol naming the Lisp function to be created.
- @item arg-name
- A symbol.
- @item return-type
- @itemx arg-type
- A foreign type.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}.
- @item library
- A symbol designating a foreign library.
- @item docstring
- A documentation string.
- @end table
- @subheading Description
- The @code{defcfun} macro provides a declarative interface for defining
- Lisp functions that call foreign functions.
- When one of @var{lisp-name} or @var{foreign-name} is omitted, the
- other is automatically derived using the following rules:
- @itemize
- @item
- Foreign names are converted to Lisp names by uppercasing and replacing
- underscores with hyphens.
- @item
- Lisp names are converted to foreign names by lowercasing and replacing
- hyphens with underscores.
- @end itemize
- If you place the symbol @code{&rest} in the end of the argument list
- after the fixed arguments, @code{defcfun} will treat the foreign
- function as a @strong{variadic function}. The variadic arguments
- should be passed in a way similar to what @code{foreign-funcall} would
- expect. Unlike @code{foreign-funcall} though, @code{defcfun} will take
- care of doing argument promotion. Note that in this case
- @code{defcfun} will generate a Lisp @emph{macro} instead of a
- function and will only work for Lisps that support
- @code{foreign-funcall.}
- If a foreign structure is to be passed or returned by value (that is,
- the type is of the form @code{(:struct ...)}), then the cffi-libffi system
- must be loaded, which in turn depends on
- @uref{http://sourceware.org/libffi/,libffi}, including the header files.
- Failure to load that system will result in an error.
- Variadic functions cannot at present accept or return structures by
- value.
- @subheading Examples
- @lisp
- (defcfun "strlen" :int
- "Calculate the length of a string."
- (n :string))
- CFFI> (strlen "123")
- @result{} 3
- @end lisp
- @lisp
- (defcfun ("abs" c-abs) :int (n :int))
- CFFI> (c-abs -42)
- @result{} 42
- @end lisp
- Function without arguments:
- @lisp
- (defcfun "rand" :int)
- CFFI> (rand)
- @result{} 1804289383
- @end lisp
- Variadic function example:
- @lisp
- (defcfun "sprintf" :int
- (str :pointer)
- (control :string)
- &rest)
- CFFI> (with-foreign-pointer-as-string (s 100)
- (sprintf s "%c %d %.2f %s" :char 90 :short 42 :float pi
- :string "super-locrian"))
- @result{} "A 42 3.14 super-locrian"
- @end lisp
- @subheading See Also
- @seealso{foreign-funcall} @*
- @seealso{foreign-funcall-pointer} @*
- @seealso{foreign-funcall-varargs} @*
- @seealso{foreign-funcall-pointer-varargs}
- @c ===================================================================
- @c FOREIGN-FUNCALL
- @page
- @node foreign-funcall, foreign-funcall-pointer, defcfun, Functions
- @heading foreign-funcall
- @subheading Syntax
- @Macro{foreign-funcall name-and-options &rest arguments @res{} return-value}
- @var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
- @var{name-and-options} ::= @var{name} | (@var{name} &key @var{library} @var{convention}) @*
- @subheading Arguments and Values
- @table @var
- @item name
- A Lisp string.
- @item arg-type
- A foreign type.
- @item arg
- An argument of type @var{arg-type}.
- @item return-type
- A foreign type, @code{:void} by default.
- @item return-value
- A lisp object.
- @item library
- A lisp symbol; not evaluated.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}.
- @end table
- @subheading Description
- The @code{foreign-funcall} macro is the main primitive for calling
- foreign functions.
- If a foreign structure is to be passed or returned by value (that is,
- the type is of the form @code{(:struct ...)}), then the cffi-libffi system
- must be loaded, which in turn depends on
- @uref{http://sourceware.org/libffi/,libffi}, including the header files.
- Failure to load that system will result in an error.
- Variadic functions cannot at present accept or return structures by
- value.
- @emph{Note: The return value of foreign-funcall on functions with a
- :void return type is still undefined.}
- @subheading Implementation-specific Notes
- @itemize
- @item
- Corman Lisp does not support @code{foreign-funcall}. On
- implementations that @strong{don't} support @code{foreign-funcall}
- @code{cffi-sys::no-foreign-funcall} will be present in
- @code{*features*}. Note: in these Lisps you can still use the
- @code{defcfun} interface.
- @end itemize
- @subheading Examples
- @lisp
- CFFI> (foreign-funcall "strlen" :string "foo" :int)
- @result{} 3
- @end lisp
- Given the C code:
- @example
- void print_number(int n)
- @{
- printf("N: %d\n", n);
- @}
- @end example
- @lisp
- CFFI> (foreign-funcall "print_number" :int 123456)
- @print{} N: 123456
- @result{} NIL
- @end lisp
- @noindent
- Or, equivalently:
- @lisp
- CFFI> (foreign-funcall "print_number" :int 123456 :void)
- @print{} N: 123456
- @result{} NIL
- @end lisp
- @lisp
- CFFI> (foreign-funcall "printf" :string (format nil "%s: %d.~%")
- :string "So long and thanks for all the fish"
- :int 42 :int)
- @print{} So long and thanks for all the fish: 42.
- @result{} 41
- @end lisp
- @subheading See Also
- @seealso{defcfun} @*
- @seealso{foreign-funcall-pointer}
- @c ===================================================================
- @c FOREIGN-FUNCALL-POINTER
- @page
- @node foreign-funcall-pointer, foreign-funcall-varargs, foreign-funcall, Functions
- @heading foreign-funcall-pointer
- @subheading Syntax
- @Macro{foreign-funcall-pointer pointer options &rest arguments @res{} return-value}
- @var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
- @var{options} ::= (&key @var{convention}) @*
- @subheading Arguments and Values
- @table @var
- @item pointer
- A foreign pointer.
- @item arg-type
- A foreign type.
- @item arg
- An argument of type @var{arg-type}.
- @item return-type
- A foreign type, @code{:void} by default.
- @item return-value
- A lisp object.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}.
- @end table
- @subheading Description
- The @code{foreign-funcall} macro is the main primitive for calling
- foreign functions.
- @emph{Note: The return value of foreign-funcall on functions with a
- :void return type is still undefined.}
- @subheading Implementation-specific Notes
- @itemize
- @item
- Corman Lisp does not support @code{foreign-funcall}. On
- implementations that @strong{don't} support @code{foreign-funcall}
- @code{cffi-sys::no-foreign-funcall} will be present in
- @code{*features*}. Note: in these Lisps you can still use the
- @code{defcfun} interface.
- @end itemize
- @subheading Examples
- @lisp
- CFFI> (foreign-funcall-pointer (foreign-symbol-pointer "abs") ()
- :int -42 :int)
- @result{} 42
- @end lisp
- @subheading See Also
- @seealso{defcfun} @*
- @seealso{foreign-funcall}
- @c ===================================================================
- @c FOREIGN-FUNCALL-VARARGS
- @page
- @node foreign-funcall-varargs, foreign-funcall-pointer-varargs, foreign-funcall-pointer, Functions
- @heading foreign-funcall-varargs
- @subheading Syntax
- @Macro{foreign-funcall-varargs name-and-options (fixed-arguments) &rest arguments @res{} return-value}
- @var{fixed-arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
- @var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
- @var{name-and-options} ::= @var{name} | (@var{name} &key @var{library} @var{convention}) @*
- @subheading Arguments and Values
- @table @var
- @item name
- A Lisp string.
- @item arg-type
- A foreign type.
- @item arg
- An argument of type @var{arg-type}.
- @item return-type
- A foreign type, @code{:void} by default.
- @item return-value
- A lisp object.
- @item library
- A lisp symbol; not evaluated.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}.
- @end table
- @subheading Description
- The @code{foreign-funcall-varargs} macro is the main primitive for
- calling foreign variadic functions. It behaves similarily to
- @code{foreign-funcall} except @code{fixed-arguments} are distinguished
- from the remaining arguments.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-pointer-as-string (s 100)
- (setf (mem-ref s :char) 0)
- (foreign-funcall-varargs
- "sprintf" (:pointer s :string) "%.2f")
- :double (coerce pi 'double-float) :int))
- @result{} 3.14
- @end lisp
- @c ===================================================================
- @c FOREIGN-FUNCALL-POINTER-VARARGS
- @page
- @node foreign-funcall-pointer-varargs, translate-camelcase-name, foreign-funcall-varargs, Functions
- @heading foreign-funcall-pointer-varargs
- @subheading Syntax
- @Macro{foreign-funcall-pointer-varargs pointer options (fixed-arguments) &rest arguments @res{} return-value}
- @var{fixed-arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
- @var{arguments} ::= @{ @var{arg-type} @var{arg} @}* [@var{return-type}] @*
- @var{options} ::= (&key @var{convention}) @*
- @subheading Arguments and Values
- @table @var
- @item pointer
- A foreign pointer.
- @item arg-type
- A foreign type.
- @item arg
- An argument of type @var{arg-type}.
- @item return-type
- A foreign type, @code{:void} by default.
- @item return-value
- A lisp object.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}.
- @end table
- @subheading Description
- The @code{foreign-funcall-pointer-varargs} macro is the main primitive
- for calling foreign variadic functions. It behaves similarily to
- @code{foreign-funcall-pointer} except @code{fixed-arguments} are
- distinguished from the remaining arguments.
- @subheading Examples
- @lisp
- CFFI> (with-foreign-pointer-as-string (s 100)
- (setf (mem-ref s :char) 0)
- (foreign-funcall-pointer-varargs
- (foreign-symbol-pointer "sprintf") () (:pointer s :string "%.2f")
- :double (coerce pi 'double-float) :int))
- @result{} 3.14
- @end lisp
- @c ===================================================================
- @c TRANSLATE-CAMELCASE-NAME
- @page
- @node translate-camelcase-name, translate-name-from-foreign, foreign-funcall-pointer-varargs, Functions
- @heading translate-camelcase-name
- @subheading Syntax
- @Function{translate-camelcase-name name &key upper-initial-p special-words @res{} return-value}
- @subheading Arguments and Values
- @table @var
- @item name
- Either a symbol or a string.
- @item upper-initial-p
- A generalized boolean.
- @item special words
- A list of strings.
- @item return-value
- If @var{name} is a symbol, this is a string, and vice versa.
- @end table
- @subheading Description
- @code{translate-camelcase-name} is a helper function for
- specializations of @code{translate-name-from-foreign} and
- @code{translate-name-to-foreign}. It handles the common case of
- converting between foreign camelCase names and lisp
- names. @var{upper-initial-p} indicates whether the first letter of the
- foreign name should be uppercase. @var{special-words} is a list of
- strings that should be treated atomically in translation. This list is
- case-sensitive.
- @subheading Examples
- @lisp
- CFFI> (translate-camelcase-name some-xml-function)
- @result{} "someXmlFunction"
- CFFI> (translate-camelcase-name some-xml-function :upper-initial-p t)
- @result{} "SomeXmlFunction"
- CFFI> (translate-camelcase-name some-xml-function :special-words '("XML"))
- @result{} "someXMLFunction"
- CFFI> (translate-camelcase-name "someXMLFunction")
- @result{} SOME-X-M-L-FUNCTION
- CFFI> (translate-camelcase-name "someXMLFunction" :special-words '("XML"))
- @result{} SOME-XML-FUNCTION
- @end lisp
- @subheading See Also
- @seealso{translate-name-from-foreign} @*
- @seealso{translate-name-to-foreign} @*
- @seealso{translate-underscore-separated-name}
- @c ===================================================================
- @c TRANSLATE-NAME-FROM-FOREIGN
- @page
- @node translate-name-from-foreign, translate-name-to-foreign, translate-camelcase-name, Functions
- @heading translate-name-from-foreign
- @subheading Syntax
- @Function{translate-name-from-foreign foreign-name package &optional varp @res{} symbol}
- @subheading Arguments and Values
- @table @var
- @item foreign-name
- A string denoting a foreign function.
- @item package
- A Lisp package
- @item varp
- A generalized boolean.
- @item symbol
- The Lisp symbol to be used a function name.
- @end table
- @subheading Description
- @code{translate-name-from-foreign} is used by @ref{defcfun} to handle
- the conversion of foreign names to lisp names. By default, it
- translates using @ref{translate-underscore-separated-name}. However,
- you can create specialized methods on this function to make
- translating more closely match the foreign library's naming
- conventions.
- Specialize @var{package} on some package. This allows other packages
- to load libraries with different naming conventions.
- @subheading Examples
- @lisp
- CFFI> (defcfun "someXmlFunction" ...)
- @result{} SOMEXMLFUNCTION
- CFFI> (defmethod translate-name-from-foreign ((spec string)
- (package (eql *package*))
- &optional varp)
- (let ((name (translate-camelcase-name spec)))
- (if varp (intern (format nil "*~a*" name)) name)))
- @result{} #<STANDARD-METHOD TRANSLATE-NAME-FROM-FOREIGN (STRING (EQL #<Package "SOME-PACKAGE">))>
- CFFI> (defcfun "someXmlFunction" ...)
- @result{} SOME-XML-FUNCTION
- @end lisp
- @subheading See Also
- @seealso{defcfun} @*
- @seealso{translate-camelcase-name} @*
- @seealso{translate-name-to-foreign} @*
- @seealso{translate-underscore-separated-name}
- @c ===================================================================
- @c TRANSLATE-NAME-TO-FOREIGN
- @page
- @node translate-name-to-foreign, translate-underscore-separated-name, translate-name-from-foreign, Functions
- @heading translate-name-to-foreign
- @subheading Syntax
- @Function{translate-name-to-foreign lisp-name package &optional varp @res{} string}
- @subheading Arguments and Values
- @table @var
- @item lisp-name
- A symbol naming the Lisp function to be created.
- @item package
- A Lisp package
- @item varp
- A generalized boolean.
- @item string
- The string representing the foreign function name.
- @end table
- @subheading Description
- @code{translate-name-to-foreign} is used by @ref{defcfun} to handle
- the conversion of lisp names to foreign names. By default, it
- translates using @ref{translate-underscore-separated-name}. However,
- you can create specialized methods on this function to make
- translating more closely match the foreign library's naming
- conventions.
- Specialize @var{package} on some package. This allows other packages
- to load libraries with different naming conventions.
- @subheading Examples
- @lisp
- CFFI> (defcfun some-xml-function ...)
- @result{} "some_xml_function"
- CFFI> (defmethod translate-name-to-foreign ((spec symbol)
- (package (eql *package*))
- &optional varp)
- (let ((name (translate-camelcase-name spec)))
- (if varp (subseq name 1 (1- (length name))) name)))
- @result{} #<STANDARD-METHOD TRANSLATE-NAME-TO-FOREIGN (STRING (EQL #<Package "SOME-PACKAGE">))>
- CFFI> (defcfun some-xml-function ...)
- @result{} "someXmlFunction"
- @end lisp
- @subheading See Also
- @seealso{defcfun} @*
- @seealso{translate-camelcase-name} @*
- @seealso{translate-name-from-foreign} @*
- @seealso{translate-underscore-separated-name}
- @c ===================================================================
- @c TRANSLATE-UNDERSCORE-SEPARATED-NAME
- @page
- @node translate-underscore-separated-name, , translate-name-to-foreign, Functions
- @heading translate-underscore-separated-name
- @subheading Syntax
- @Function{translate-underscore-separated-name name @res{} return-value}
- @subheading Arguments and Values
- @table @var
- @item name
- Either a symbol or a string.
- @item return-value
- If @var{name} is a symbol, this is a string, and vice versa.
- @end table
- @subheading Description
- @code{translate-underscore-separated-name} is a helper function for
- specializations of @ref{translate-name-from-foreign} and
- @ref{translate-name-to-foreign}. It handles the common case of
- converting between foreign underscore_separated names and lisp names.
- @subheading Examples
- @lisp
- CFFI> (translate-underscore-separated-name some-xml-function)
- @result{} "some_xml_function"
- CFFI> (translate-camelcase-name "some_xml_function")
- @result{} SOME-XML-FUNCTION
- @end lisp
- @subheading See Also
- @seealso{translate-name-from-foreign} @*
- @seealso{translate-name-to-foreign} @*
- @seealso{translate-camelcase-name}
- @c ===================================================================
- @c CHAPTER: Libraries
- @node Libraries, Callbacks, Functions, Top
- @chapter Libraries
- @menu
- * Defining a library::
- * Library definition style::
- Dictionary
- * close-foreign-library:: Close a foreign library.
- * *darwin-framework-directories*:: Search path for Darwin frameworks.
- * define-foreign-library:: Explain how to load a foreign library.
- * *foreign-library-directories*:: Search path for shared libraries.
- * load-foreign-library:: Load a foreign library.
- * load-foreign-library-error:: Signalled on failure of its namesake.
- * use-foreign-library:: Load a foreign library when needed.
- @end menu
- @node Defining a library, Library definition style, Libraries, Libraries
- @section Defining a library
- Almost all foreign code you might want to access exists in some kind
- of shared library. The meaning of @dfn{shared library} varies among
- platforms, but for our purposes, we will consider it to include
- @file{.so} files on @sc{unix}, frameworks on Darwin (and derivatives
- like Mac @acronym{OS X}), and @file{.dll} files on Windows.
- Bringing one of these libraries into the Lisp image is normally a
- two-step process.
- @enumerate
- @item
- Describe to @cffi{} how to load the library at some future point,
- depending on platform and other factors, with a
- @code{define-foreign-library} top-level form.
- @item
- Load the library so defined with either a top-level
- @code{use-foreign-library} form or by calling the function
- @code{load-foreign-library}.
- @end enumerate
- @xref{Tutorial-Loading,, Loading foreign libraries}, for a working
- example of the above two steps.
- @node Library definition style, close-foreign-library, Defining a library, Libraries
- @section Library definition style
- Looking at the @code{libcurl} library definition presented earlier,
- you may ask why we did not simply do this:
- @lisp
- (define-foreign-library libcurl
- (t (:default "libcurl")))
- @end lisp
- @noindent
- Indeed, this would work just as well on the computer on which I tested
- the tutorial. There are a couple of good reasons to provide the
- @file{.so}'s current version number, however. Namely, the versionless
- @file{.so} is not packaged on most @sc{unix} systems along with the
- actual, fully-versioned library; instead, it is included in the
- ``development'' package along with C headers and static @file{.a}
- libraries.
- The reason @cffi{} does not try to account for this lies in the
- meaning of the version numbers. A full treatment of shared library
- versions is beyond this manual's scope; see @ref{Versioning,, Library
- interface versions, libtool, @acronym{GNU} Libtool}, for helpful
- information for the unfamiliar. For our purposes, consider that a
- mismatch between the library version with which you tested and the
- installed library version may cause undefined
- behavior.@footnote{Windows programmers may chafe at adding a
- @sc{unix}-specific clause to @code{define-foreign-library}. Instead,
- ask why the Windows solution to library incompatibility is ``include
- your own version of every library you use with every program''.}
- @impnote{Maybe some notes should go here about OS X, which I know
- little about. --stephen}
- @c ===================================================================
- @c CLOSE-FOREIGN-LIBRARY
- @page
- @node close-foreign-library, *darwin-framework-directories*, Library definition style, Libraries
- @heading close-foreign-library
- @subheading Syntax
- @Function{close-foreign-library library @res{} success}
- @subheading Arguments and Values
- @table @var
- @item library
- A symbol or an instance of @code{foreign-library}.
- @item success
- A Lisp boolean.
- @end table
- @subheading Description
- Closes @var{library} which can be a symbol designating a library
- define through @code{define-foreign-library} or an instance of
- @code{foreign-library} as returned by @code{load-foreign-library}.
- @c @subheading Examples
- @c @xref{Tutorial-Loading,, Loading foreign libraries}.
- @subheading See Also
- @seealso{define-foreign-library} @*
- @seealso{load-foreign-library} @*
- @seealso{use-foreign-library}
- @c ===================================================================
- @c *DARWIN-FRAMEWORK-DIRECTORIES*
- @page
- @node *darwin-framework-directories*, define-foreign-library, close-foreign-library, Libraries
- @heading *darwin-framework-directories*
- @subheading Syntax
- @Variable{*darwin-framework-directories*}
- @subheading Value type
- A list, in which each element is a string, a pathname, or a simple
- Lisp expression.
- @subheading Initial value
- A list containing the following, in order: an expression corresponding
- to Darwin path @file{~/Library/Frameworks/},
- @code{#P"/Library/Frameworks/"}, and
- @code{#P"/System/Library/Frameworks/"}.
- @subheading Description
- The meaning of ``simple Lisp expression'' is explained in
- @ref{*foreign-library-directories*}. In contrast to that variable,
- this is not a fallback search path; the default value described above
- is intended to be a reasonably complete search path on Darwin systems.
- @subheading Examples
- @lisp
- CFFI> (let ((lib (load-foreign-library '(:framework "OpenGL"))))
- (foreign-library-pathname lib))
- @result{} #P"/System/Library/Frameworks/OpenGL.framework/OpenGL"
- @end lisp
- @subheading See also
- @seealso{*foreign-library-directories*} @*
- @seealso{define-foreign-library}
- @c ===================================================================
- @c DEFINE-FOREIGN-LIBRARY
- @page
- @node define-foreign-library, *foreign-library-directories*, *darwin-framework-directories*, Libraries
- @heading define-foreign-library
- @subheading Syntax
- @Macro{define-foreign-library name-and-options @{ load-clause @}* @res{} name}
- name-and-options ::= name | (name &key canary convention search-path) @*
- load-clause ::= (feature library &key convention search-path) @*
- @subheading Arguments and Values
- @table @var
- @item name
- A symbol.
- @item feature
- A feature expression.
- @item library
- A library designator.
- @item canary
- A string denoting a foreign symbol that will be searched in core
- before attempting to load the library. If that symbol is found, the
- library is assumed to be statically linked and
- @code{load-foreign-library} only marks the library as loaded.
- Some implementations (Clisp, ECL, SBCL) natively support static
- linking, sometimes referred to as a @emph{link kit}.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}
- @item search-path
- A path or list of paths where the library will be searched if not found in
- system-global directories. Paths specified in a load clause take priority over
- paths specified as library option, with *foreign-library-directories* having
- lowest priority.
- @end table
- @subheading Description
- Creates a new library designator called @var{name}. The
- @var{load-clause}s describe how to load that designator when passed to
- @code{load-foreign-library} or @code{use-foreign-library}.
- When trying to load the library @var{name}, the relevant function
- searches the @var{load-clause}s in order for the first one where
- @var{feature} evaluates to true. That happens for any of the
- following situations:
- @enumerate 1
- @item
- If @var{feature} is a symbol present in @code{common-lisp:*features*}.
- @item
- If @var{feature} is a list, depending on @code{(first @var{feature})},
- a keyword:
- @table @code
- @item :and
- All of the feature expressions in @code{(rest @var{feature})} are
- true.
- @item :or
- At least one of the feature expressions in @code{(rest @var{feature})}
- is true.
- @item :not
- The feature expression @code{(second @var{feature})} is not true.
- @end table
- @item
- Finally, if @var{feature} is @code{t}, this @var{load-clause} is
- picked unconditionally.
- @end enumerate
- Upon finding the first true @var{feature}, the library loader then
- loads the @var{library}. The meaning of ``library designator'' is
- described in @ref{load-foreign-library}.
- Functions associated to a library defined by
- @code{define-foreign-library} (e.g. through @code{defcfun}'s
- @code{:library} option, will inherit the library's options. The
- precedence is as follows:
- @enumerate 1
- @item
- @code{defcfun}/@code{foreign-funcall} specific options;
- @item
- @var{load-clause} options;
- @item
- global library options (the @var{name-and-options} argument)
- @end enumerate
- @subheading Examples
- @xref{Tutorial-Loading,, Loading foreign libraries}.
- @subheading See Also
- @seealso{close-foreign-library} @*
- @seealso{load-foreign-library}
- @c ===================================================================
- @c *FOREIGN-LIBRARY-DIRECTORIES*
- @page
- @node *foreign-library-directories*, load-foreign-library, define-foreign-library, Libraries
- @heading *foreign-library-directories*
- @subheading Syntax
- @Variable{*foreign-library-directories*}
- @subheading Value type
- A list, in which each element is a string, a pathname, or a simple
- Lisp expression.
- @subheading Initial value
- The empty list.
- @subheading Description
- You should not have to use this variable.
- Most, if not all, Lisps supported by @cffi{} have a reasonable default
- search algorithm for foreign libraries. For example, Lisps for
- @sc{unix} usually call
- @uref{http://www.opengroup.org/onlinepubs/009695399/functions/dlopen.html,,
- @code{dlopen(3)}}, which in turn looks in the system library
- directories. Only if that fails does @cffi{} look for the named
- library file in these directories, and load it from there if found.
- Thus, this is intended to be a @cffi{}-only fallback to the library
- search configuration provided by your operating system. For example,
- if you distribute a foreign library with your Lisp package, you can
- add the library's containing directory to this list and portably
- expect @cffi{} to find it.
- A @dfn{simple Lisp expression} is intended to provide functionality
- commonly used in search paths such as
- @acronym{ASDF}'s@footnote{@xref{Using asdf to load systems,,, asdf,
- asdf: another system definition facility}, for information on
- @code{asdf:*central-registry*}.}, and is defined recursively as
- follows:@footnote{See @code{mini-eval} in @file{libraries.lisp} for
- the source of this definition. As is always the case with a Lisp
- @code{eval}, it's easier to understand the Lisp definition than the
- english.}
- @enumerate
- @item
- A list, whose @samp{first} is a function designator, and whose
- @samp{rest} is a list of simple Lisp expressions to be evaluated and
- passed to the so-designated function. The result is the result of the
- function call.
- @item
- A symbol, whose result is its symbol value.
- @item
- Anything else evaluates to itself.
- @end enumerate
- The result of evaluating the @dfn{simple Lisp expression} should yield
- a @emph{designator} for a @emph{list} of @emph{pathname designators}.
- @strong{Note}: in Common Lisp, @code{#p"/foo/bar"} designates the
- @emph{bar} file within the @emph{/foo} directory whereas
- @code{#p"/foo/bar/"} designates the @emph{/foo/bar} directory. Keep
- that in mind when customising the value of
- @code{*foreign-library-directories*}.
- @subheading Examples
- @example
- $ ls
- @print{} liblibli.so libli.lisp
- @end example
- @noindent
- In @file{libli.lisp}:
- @lisp
- (pushnew #P"/home/sirian/lisp/libli/" *foreign-library-directories*
- :test #'equal)
- (load-foreign-library '(:default "liblibli"))
- @end lisp
- @noindent
- The following example would achieve the same effect:
- @lisp
- (pushnew '(merge-pathnames #p"lisp/libli/" (user-homedir-pathname))
- *foreign-library-directories*
- :test #'equal)
- @result{} ((MERGE-PATHNAMES #P"lisp/libli/" (USER-HOMEDIR-PATHNAME)))
- (load-foreign-library '(:default "liblibli"))
- @end lisp
- @subheading See also
- @seealso{*darwin-framework-directories*} @*
- @seealso{define-foreign-library}
- @c ===================================================================
- @c LOAD-FOREIGN-LIBRARY
- @page
- @node load-foreign-library, load-foreign-library-error, *foreign-library-directories*, Libraries
- @heading load-foreign-library
- @subheading Syntax
- @Function{load-foreign-library library-designator @res{} library}
- @subheading Arguments and Values
- @table @var
- @item library-designator
- A library designator.
- @item library-designator
- An instance of @code{foreign-library}.
- @end table
- @subheading Description
- Load the library indicated by @var{library-designator}. A @dfn{library
- designator} is defined as follows:
- @enumerate
- @item
- If a symbol, is considered a name previously defined with
- @code{define-foreign-library}.
- @item
- If a string or pathname, passed as a namestring directly to the
- implementation's foreign library loader. If that fails, search the
- directories in @code{*foreign-library-directories*} with
- @code{cl:probe-file}; if found, the absolute path is passed to the
- implementation's loader.
- @item
- If a list, the meaning depends on @code{(first @var{library})}:
- @table @code
- @item :framework
- The second list element is taken to be a Darwin framework name, which
- is then searched in @code{*darwin-framework-directories*}, and loaded
- when found.
- @item :or
- Each remaining list element, itself a @dfn{library designator}, is loaded in
- order, until one succeeds.
- @item :default
- The name is transformed according to the platform's naming convention
- to shared libraries, and the resultant string is loaded as a @dfn{library
- designator}. For example, on @sc{unix}, the name is suffixed with
- @file{.so}.
- @end table
- @end enumerate
- If the library is already loaded it will be reloaded.
- If the load fails, signal a @code{load-foreign-library-error}.
- @strong{Please note:} For system libraries, you should not need to
- specify the directory containing the library. Each operating system
- has its own idea of a default search path, and you should rely on it
- when it is reasonable.
- @subheading Implementation-specific Notes
- On ECL platforms where its dynamic FFI is not supported (ie. when
- @code{:dffi} is not present in @code{*features*}),
- @code{cffi:load-foreign-library} does not work and you must use ECL's
- own @code{ffi:load-foreign-library} with a constant string argument.
- @subheading Examples
- @xref{Tutorial-Loading,, Loading foreign libraries}.
- @subheading See Also
- @seealso{close-foreign-library} @*
- @seealso{*darwin-framework-directories*} @*
- @seealso{define-foreign-library} @*
- @seealso{*foreign-library-directories*} @*
- @seealso{load-foreign-library-error} @*
- @seealso{use-foreign-library}
- @c ===================================================================
- @c LOAD-FOREIGN-LIBRARY-ERROR
- @page
- @node load-foreign-library-error, use-foreign-library, load-foreign-library, Libraries
- @heading load-foreign-library-error
- @subheading Syntax
- @Condition{load-foreign-library-error}
- @subheading Class precedence list
- @code{load-foreign-library-error}, @code{error},
- @code{serious-condition}, @code{condition}, @code{t}
- @subheading Description
- Signalled when a foreign library load completely fails. The exact
- meaning of this varies depending on the real conditions at work, but
- almost universally, the implementation's error message is useless.
- However, @cffi{} does provide the useful restarts @code{retry} and
- @code{use-value}; invoke the @code{retry} restart to try loading the
- foreign library again, or the @code{use-value} restart to try loading
- a different foreign library designator.
- @subheading See also
- @seealso{load-foreign-library}
- @c ===================================================================
- @c USE-FOREIGN-LIBRARY
- @page
- @node use-foreign-library, , load-foreign-library-error, Libraries
- @heading use-foreign-library
- @subheading Syntax
- @Macro{use-foreign-library name}
- @subheading Arguments and values
- @table @var
- @item name
- A library designator; unevaluated.
- @end table
- @subheading Description
- @xref{load-foreign-library}, for the meaning of ``library
- designator''. This is intended to be the top-level form used
- idiomatically after a @code{define-foreign-library} form to go ahead
- and load the library. @c ; it also sets the ``current foreign library''.
- Finally, on implementations where the regular evaluation rule is
- insufficient for foreign library loading, it loads it at the required
- time.@footnote{Namely, @acronym{CMUCL}. See
- @code{use-foreign-library} in @file{libraries.lisp} for details.}
- @c current foreign library is a concept created a few hours ago as of
- @c this writing. It is not actually used yet, but probably will be.
- @subheading Examples
- @xref{Tutorial-Loading,, Loading foreign libraries}.
- @subheading See also
- @seealso{load-foreign-library}
- @c ===================================================================
- @c CHAPTER: Callbacks
- @node Callbacks, The Groveller, Libraries, Top
- @chapter Callbacks
- @menu
- Dictionary
- * callback::
- * defcallback::
- * get-callback::
- @end menu
- @c ===================================================================
- @c CALLBACK
- @page
- @node callback, defcallback, Callbacks, Callbacks
- @heading callback
- @subheading Syntax
- @Macro{callback symbol @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item symbol
- A symbol denoting a callback.
- @item pointer
- @itemx new-value
- A pointer.
- @end table
- @subheading Description
- The @code{callback} macro is analogous to the standard CL special
- operator @code{function} and will return a pointer to the callback
- denoted by the symbol @var{name}.
- @subheading Examples
- @lisp
- CFFI> (defcallback sum :int ((a :int) (b :int))
- (+ a b))
- @result{} SUM
- CFFI> (callback sum)
- @result{} #<A Mac Pointer #x102350>
- @end lisp
- @subheading See Also
- @seealso{get-callback} @*
- @seealso{defcallback}
- @c ===================================================================
- @c DEFCALLBACK
- @page
- @node defcallback, get-callback, callback, Callbacks
- @heading defcallback
- @subheading Syntax
- @Macro{defcallback name-and-options return-type arguments &body body @res{} name}
- name-and-options ::= name | (name &key convention) @*
- arguments ::= (@{ (arg-name arg-type) @}*) @*
- @subheading Arguments and Values
- @table @var
- @item name
- A symbol naming the callback created.
- @item return-type
- The foreign type for the callback's return value.
- @item arg-name
- A symbol.
- @item arg-type
- A foreign type.
- @item convention
- One of @code{:cdecl} (default) or @code{:stdcall}.
- @end table
- @subheading Description
- The @code{defcallback} macro defines a Lisp function that can be called
- from C. The arguments passed to this function will be converted to the
- appropriate Lisp representation and its return value will be converted
- to its C representation.
- This Lisp function can be accessed by the @code{callback} macro or the
- @code{get-callback} function.
- @strong{Portability note:} @code{defcallback} will not work correctly
- on some Lisps if it's not a top-level form.
- @subheading Examples
- @lisp
- (defcfun "qsort" :void
- (base :pointer)
- (nmemb :int)
- (size :int)
- (fun-compar :pointer))
- (defcallback < :int ((a :pointer) (b :pointer))
- (let ((x (mem-ref a :int))
- (y (mem-ref b :int)))
- (cond ((> x y) 1)
- ((< x y) -1)
- (t 0))))
- CFFI> (with-foreign-object (array :int 10)
- ;; @lispcmt{Initialize array.}
- (loop for i from 0 and n in '(7 2 10 4 3 5 1 6 9 8)
- do (setf (mem-aref array :int i) n))
- ;; @lispcmt{Sort it.}
- (qsort array 10 (foreign-type-size :int) (callback <))
- ;; @lispcmt{Return it as a list.}
- (loop for i from 0 below 10
- collect (mem-aref array :int i)))
- @result{} (1 2 3 4 5 6 7 8 9 10)
- @end lisp
- @subheading See Also
- @seealso{callback} @*
- @seealso{get-callback}
- @c ===================================================================
- @c GET-CALLBACK
- @page
- @node get-callback, , defcallback, Callbacks
- @heading get-callback
- @subheading Syntax
- @Accessor{get-callback symbol @res{} pointer}
- @subheading Arguments and Values
- @table @var
- @item symbol
- A symbol denoting a callback.
- @item pointer
- A pointer.
- @end table
- @subheading Description
- This is the functional version of the @code{callback} macro. It
- returns a pointer to the callback named by @var{symbol} suitable, for
- example, to pass as arguments to foreign functions.
- @subheading Examples
- @lisp
- CFFI> (defcallback sum :int ((a :int) (b :int))
- (+ a b))
- @result{} SUM
- CFFI> (get-callback 'sum)
- @result{} #<A Mac Pointer #x102350>
- @end lisp
- @subheading See Also
- @seealso{callback} @*
- @seealso{defcallback}
- @c ===================================================================
- @c CHAPTER: The Groveller
- @node The Groveller, Limitations, Callbacks, Top
- @chapter The Groveller
- @cffi{}-Grovel is a tool which makes it easier to write @cffi{}
- declarations for libraries that are implemented in C. That is, it
- grovels through the system headers, getting information about types
- and structures, so you don't have to. This is especially important
- for libraries which are implemented in different ways by different
- vendors, such as the @sc{unix}/@sc{posix} functions. The @cffi{}
- declarations are usually quite different from platform to platform,
- but the information you give to @cffi{}-Grovel is the same. Hence,
- much less work is required!
- If you use @acronym{ASDF}, @cffi{}-Grovel is integrated, so that it
- will run automatically when your system is building. This feature was
- inspired by SB-Grovel, a similar @acronym{SBCL}-specific project.
- @cffi{}-Grovel can also be used without @acronym{ASDF}.
- @section Building FFIs with CFFI-Grovel
- @cffi{}-Grovel uses a specification file (*.lisp) describing the
- features that need groveling. The C compiler is used to retrieve this
- data and write a Lisp file (*.cffi.lisp) which contains the necessary
- @cffi{} definitions to access the variables, structures, constants, and
- enums mentioned in the specification.
- @c This is most similar to the SB-Grovel package, upon which it is
- @c based. Unlike SB-Grovel, we do not currently support defining
- @c regular foreign functions in the specification file; those are best
- @c defined in normal Lisp code.
- @cffi{}-Grovel provides an @acronym{ASDF} component for handling the
- necessary calls to the C compiler and resulting file management.
- @c See the included CFFI-Unix package for an example of how to
- @c integrate a specification file with ASDF-built packages.
- @menu
- * Groveller Syntax:: How grovel files should look like.
- * Groveller ASDF Integration:: ASDF components for grovel files.
- * Groveller Implementation Notes:: Implementation notes.
- * Wrapper for Inline/Static Functions and Macros:: Wrapper
- @end menu
- @node Groveller Syntax, Groveller ASDF Integration, The Groveller, The Groveller
- @section Specification File Syntax
- The specification files are read by the normal Lisp reader, so they
- have syntax very similar to normal Lisp code. In particular,
- semicolon-comments and reader-macros will work as expected.
- There are several forms recognized by @cffi{}-Grovel:
- @deffn {Grovel Form} progn &rest forms
- Processes a list of forms. Useful for conditionalizing several
- forms. For example:
- @end deffn
- @lisp
- #+freebsd
- (progn
- (constant (ev-enable "EV_ENABLE"))
- (constant (ev-disable "EV_DISABLE")))
- @end lisp
- @deffn {Grovel Form} include &rest files
- Include the specified files (specified as strings) in the generated C
- source code.
- @end deffn
- @deffn {Grovel Form} in-package symbol
- Set the package to be used for the final Lisp output.
- @end deffn
- @deffn {Grovel Form} ctype lisp-name size-designator
- Define a @cffi{} foreign type for the string in @var{size-designator},
- e.g. @code{(ctype :pid "pid_t")}.
- @end deffn
- @deffn {Grovel Form} constant (lisp-name &rest c-names) &key type documentation optional
- Search for the constant named by the first @var{c-name} string found
- to be known to the C preprocessor and define it as @var{lisp-name}.
- The @var{type} keyword argument specifies how to grovel the constant:
- either @code{integer} (the default) or @code{double-float}. If
- @var{optional} is true, no error will be raised if all the
- @var{c-names} are unknown. If @var{lisp-name} is a keyword, the actual
- constant will be a symbol of the same name interned in the current
- package.
- @end deffn
- @deffn {Grovel Form} feature lisp-feature-name c-name &key feature-list
- Adds @var{lisp-feature-name} to the list @var{feature-list} if the @var{c-name}
- string is known to the C preprocessor. @var{feature-list} defaults
- to @code{cl:*features*}.
- @end deffn
- @deffn {Grovel Form} define name &optional value
- Defines an additional C preprocessor symbol, which is useful for
- altering the behavior of included system headers.
- @end deffn
- @deffn {Grovel Form} cc-flags &rest flags
- Adds @var{cc-flags} to the command line arguments used for the C compiler
- invocation.
- @end deffn
- @deffn {Grovel Form} pkg-config-cflags pkg &key optional
- Adds @var{pkg} to the command line arguments for the external program
- @code{pkg-config} and runs it to retrieve the relevant include flags
- used for the C compiler invocation. This syntax can be used instead of
- hard-coding paths using @code{cc-flags}, and ensures that include
- flags are added correctly on the build system. Assumes
- @code{pkg-config} is installed and working. @var{pkg} is a string
- that identifies an installed @code{pkg-config} package. See the
- pkg-config manual for more information. If @var{optional} is true,
- failure to execute @code{pkg-config} does @emph{not} abort
- compilation.
- @end deffn
- @deffn {Grovel Form} cstruct lisp-name c-name slots
- Define a @cffi{} foreign struct with the slot data specfied. Slots
- are of the form @code{(lisp-name c-name &key type count (signed t))}.
- @end deffn
- @deffn {Grovel Form} cunion lisp-name c-name slots
- Identical to @code{cstruct}, but defines a @cffi{} foreign union.
- @end deffn
- @deffn {Grovel Form} cstruct-and-class c-name slots
- Defines a @cffi{} foreign struct, as with @code{cstruct} and defines a
- @acronym{CLOS} class to be used with it. This is useful for mapping
- foreign structures to application-layer code that shouldn't need to
- worry about memory allocation issues.
- @end deffn
- @deffn {Grovel Form} cvar namespec type &key read-only
- Defines a foreign variable of the specified type, even if that
- variable is potentially a C preprocessor pseudo-variable. e.g.
- @code{(cvar ("errno" errno) errno-values)}, assuming that errno-values
- is an enum or equivalent to type @code{:int}.
- The @var{namespec} is similar to the one used in @ref{defcvar}.
- @end deffn
- @deffn {Grovel Form} cenum name-and-opts &rest elements
- Defines a true C enum, with elements specified as @code{((lisp-name
- &rest c-names) &key optional documentation)}.
- @var{name-and-opts} can be either a symbol as name, or a list
- @code{(name &key base-type define-constants)}. If @var{define-constants}
- is non-null, a Lisp constant will be defined for each enum member.
- @end deffn
- @deffn {Grovel Form} constantenum name-and-opts &rest elements
- Defines an enumeration of pre-processor constants, with elements
- specified as @code{((lisp-name &rest c-names) &key optional
- documentation)}.
- @var{name-and-opts} can be either a symbol as name, or a list
- @code{(name &key base-type define-constants)}. If @var{define-constants}
- is non-null, a Lisp constant will be defined for each enum member.
- This example defines @code{:af-inet} to represent the value held by
- @code{AF_INET} or @code{PF_INET}, whichever the pre-processor finds
- first. Similarly for @code{:af-packet}, but no error will be
- signalled if the platform supports neither @code{AF_PACKET} nor
- @code{PF_PACKET}.
- @end deffn
- @lisp
- (constantenum address-family
- ((:af-inet "AF_INET" "PF_INET")
- :documentation "IPv4 Protocol family")
- ((:af-local "AF_UNIX" "AF_LOCAL" "PF_UNIX" "PF_LOCAL")
- :documentation "File domain sockets")
- ((:af-inet6 "AF_INET6" "PF_INET6")
- :documentation "IPv6 Protocol family")
- ((:af-packet "AF_PACKET" "PF_PACKET")
- :documentation "Raw packet access"
- :optional t))
- @end lisp
- @deffn {Grovel Form} bitfield name-and-opts &rest elements
- Defines a bitfield, with elements specified as @code{((lisp-name &rest
- c-names) &key optional documentation)}. @var{name-and-opts} can be either a
- symbol as name, or a list @code{(name &key base-type)}. For example:
- @end deffn
- @lisp
- (bitfield flags-ctype
- ((:flag-a "FLAG_A")
- :documentation "DOCU_A")
- ((:flag-b "FLAG_B" "FLAG_B_ALT")
- :documentation "DOCU_B")
- ((:flag-c "FLAG_C")
- :documentation "DOCU_C"
- :optional t))
- @end lisp
- @c ===================================================================
- @c SECTION: Groveller ASDF Integration
- @node Groveller ASDF Integration, Groveller Implementation Notes, Groveller Syntax, The Groveller
- @section ASDF Integration
- An example software project might contain four files; an
- @acronym{ASDF} file, a package definition file, an implementation
- file, and a @cffi{}-Grovel specification file.
- The @acronym{ASDF} file defines the system and its dependencies.
- Notice the use of @code{eval-when} to ensure @cffi{}-Grovel is present
- and the use of @code{(cffi-grovel:grovel-file name &key cc-flags)}
- instead of @code{(:file name)}.
- The @file{example-software.asd} file would look like that:
- @lisp
- ;;; @lispcmt{CFFI-Grovel is needed for processing grovel-file components}
- (defsystem "example-software"
- :defsystem-depends-on ("cffi-grovel")
- :depends-on ("cffi")
- :serial t
- :components
- ((:file "package")
- (:cffi-grovel-file "example-grovelling")
- (:cffi-wrapper-file "example-wrappers")
- (:file "example")))
- @end lisp
- The @file{package.lisp} file would contain one or several
- @code{defpackage} forms, to remove circular dependencies and make
- building the project easier. Note that you may or may not want to
- @code{:use} your internal package.
- @impnote{Note that it's a not a good idea to @code{:use} when names may
- clash with, say, CL symbols.
- Or you could use @code{uiop:define-package} and its @code{:mix} option.}
- @lisp
- (defpackage #:example-internal
- (:use)
- (:nicknames #:exampleint))
- (defpackage #:example-software
- (:export ...)
- (:use #:cl #:cffi #:exampleint))
- @end lisp
- The internal package is created by Lisp code output from the C program
- written by @cffi{}-Grovel; if your specification file is
- @file{exampleint.lisp}, the @file{exampleint.cffi.lisp} file will contain the
- @cffi{} definitions needed by the rest of your project.
- @xref{Groveller Syntax}.
- @node Groveller Implementation Notes, Wrapper for Inline/Static Functions and Macros, Groveller ASDF Integration, The Groveller
- @section Implementation Notes
- @cffi{}-Grovel will generate many files that not only architecture-specific,
- but also implementation-specific, and should not be distributed.
- ASDF will generate these files in its output cache;
- if you build with multiple architectures (e.g. with NFS/AFS home
- directories) or implementations, it is critical for avoiding clashes
- to keep this cache in an implementation-dependent directory (as is the
- default).
- For @code{foo-internal.lisp}, the resulting @code{foo-internal.c},
- @code{foo-internal}, and @code{foo-internal.cffi.lisp} are all
- platform-specific, either because of possible reader-macros in
- foo-internal.lisp, or because of varying C environments on the host
- system. For this reason, it is not helpful to distribute any of those
- files; end users building @cffi{}-Grovel based software will need
- @code{cffi}-Grovel anyway.
- @impnote{For now, after some experimentation with @sc{clisp} having no
- long-long, it seems appropriate to assert that the generated @code{.c}
- files are architecture and operating-system dependent, but
- lisp-implementation independent. This way the same @code{.c} file
- (and so the same @code{.grovel-tmp.lisp} file) will be shareable
- between the implementations running on a given system.}
- @c TODO: document the new wrapper stuff.
- @node Wrapper for Inline/Static Functions and Macros, , Groveller Implementation Notes, The Groveller
- @section Wrapper for Inline/Static Functions and Macros
- In a shared library, information in static/inlined functions and
- macros are already removed during the compilation. Wrapper file
- enables to write an uninlined function wrapping the call to them.
- A wrapper file compilation/loading proceeds as follows:
- Unlike groveller which generates C code that emits lisp files
- containing cffi definitions, it generates C code, compiles it as a
- shared library, loads the library, generate the cffi definitions (as
- lisp code) and then loads the lisp code.
- It has asdf integration similar to groveller.
- @lisp
- (defsystem "example-software"
- :defsystem-depends-on ("cffi-grovel")
- :depends-on ("cffi")
- :serial t
- :components
- ((:file "package")
- (:cffi-grovel-file "example-grovelling")
- (:cffi-wrapper-file "example-wrappers") ;; <<--- this part
- (:file "example")))
- @end lisp
- @deffn {Wrapper Form} defwrapper name-and-options return-type &rest args
- @end deffn
- @example
- static inline int foo(int i) @{
- return 1+i;
- @};
- #define bar(i) (1+(i))
- @end example
- @lisp
- (in-package :mypackage)
- (defwrapper ("foo" foo) :int
- (i :int))
- (defwrapper ("bar" bar) :int
- (i :int))
- @end lisp
- Other forms are similar to grovel files.
- @deffn {Wrapper Form} progn &rest forms
- Processes a list of forms. Useful for conditionalizing several
- forms. For example:
- @end deffn
- @lisp
- #+freebsd
- (progn
- (constant (ev-enable "EV_ENABLE"))
- (constant (ev-disable "EV_DISABLE")))
- @end lisp
- @deffn {Wrapper Form} include &rest files
- Include the specified files (specified as strings) in the generated C
- source code.
- @end deffn
- @deffn {Wrapper Form} in-package symbol
- Set the package to be used for the final Lisp output.
- @end deffn
- @deffn {Wrapper Form} flags &rest flags
- Adds @var{cc-flags} to the command line arguments used for the C compiler
- invocation.
- @end deffn
- @deffn {Wrapper Form} proclaim &rest proclaimations
- @end deffn
- @deffn {Wrapper Form} declaim &rest declaimations
- @end deffn
- @c ===================================================================
- @c CHAPTER: Static Linking
- @node Static Linking, Limitations, The Groveller, Top
- @chapter Static Linking
- On recent enough versions of supported implementations (currently, GNU
- CLISP 2.49 or later, CMUCL 2015-11 or later, and SBCL 1.2.17 or later,
- except SBCL 2.0.4), and with a recent enough ASDF (3.1.2 or later),
- you can create a statically linked Lisp executable image (or a
- standalone application executable) that includes all the C extensions
- defined via @ref{The Groveller}'s @code{:cffi-wrapper-file} ASDF
- components (and any other such objects output by
- @code{asdf:compile-op}), as well as those defined by @code{:c-file} or
- @code{:o-file} ASDF components, and your Lisp code. This makes it
- easier to deliver your code as a single file.
- Note that the resulting binary will typically still depend on any
- shared libraries loaded via @xref{load-foreign-library} or
- @xref{use-foreign-library} as well as core libraries such as
- @code{libc}.
- To dump a statically linked executable image, use:
- @lisp
- (asdf:load-system :cffi-grovel)
- (asdf:operate :static-image-op :example-software)
- @end lisp
- To dump a statically linked executable standalone application, use:
- @lisp
- (asdf:load-system :cffi-grovel)
- (asdf:operate :static-program-op :example-software)
- @end lisp
- See @uref{https://common-lisp.net/project/asdf/,,the ASDF
- manual} for documentation about @code{image-op} and @code{program-op}
- which are the parent operation classes that behave similarly except
- they don't statically link C code.
- @impnote{There is also an operation @code{:static-runtime-op} to create the
- statically linked runtime alone, but it's admittedly not very useful
- except as an intermediate step dependency towards building
- @code{:static-image-op} or @code{:static-program-op}.}
- @c ===================================================================
- @c CHAPTER: Limitations
- @node Limitations, Platform-specific features, The Groveller, Top
- @chapter Limitations
- These are @cffi{}'s limitations across all platforms; for information
- on the warts on particular Lisp implementations, see
- @ref{Implementation Support}.
- @itemize @bullet
- @item
- The tutorial includes a treatment of the primary, intractable
- limitation of @cffi{}, or any @acronym{FFI}: that the abstractions
- commonly used by C are insufficiently expressive.
- @xref{Tutorial-Abstraction,, Breaking the abstraction}, for more
- details.
- @end itemize
- @node Platform-specific features, Glossary, Limitations, Top
- @appendix Platform-specific features
- Whenever a backend doesn't support one of @cffi{}'s features, a
- specific symbol is pushed onto @code{common-lisp:*features*}. The
- meanings of these symbols follow.
- @table @var
- @item cffi-sys::flat-namespace
- This Lisp has a flat namespace for foreign symbols meaning that you
- won't be able to load two different libraries with homograph functions
- and successfully differentiate them through the @code{:library}
- option to @code{defcfun}, @code{defcvar}, etc@dots{}
- @item cffi-sys::no-foreign-funcall
- The macro @code{foreign-funcall} is @strong{not} available. On such
- platforms, the only way to call a foreign function is through
- @code{defcfun}. @xref{foreign-funcall}, and @ref{defcfun}.
- @item cffi-sys::no-long-long
- The C @code{long long} type is @strong{not} available as a foreign
- type.
- However, on such platforms @cffi{} provides its own implementation of
- the @code{long long} type for all of operations in chapters
- @ref{Foreign Types}, @ref{Pointers} and @ref{Variables}. The
- functionality described in @ref{Functions} and @ref{Callbacks} will
- not be available.
- 32-bit Lispworks 5.0+ is an exception. In addition to the @cffi{}
- implementation described above, Lispworks itself implements the
- @code{long long} type for @ref{Functions}. @ref{Callbacks} are still
- missing @code{long long} support, though.
- @item cffi-sys::no-stdcall
- This Lisp doesn't support the @code{stdcall} calling convention. Note
- that it only makes sense to support @code{stdcall} on (32-bit) x86
- platforms.
- @end table
- @node Glossary, Comprehensive Index, Platform-specific features, Top
- @appendix Glossary
- @table @dfn
- @item aggregate type
- A @cffi{} type for C data defined as an organization of data of simple
- type; in structures and unions, which are themselves aggregate types,
- they are represented by value.
- @item foreign value
- This has two meanings; in any context, only one makes sense.
- When using type translators, the foreign value is the lower-level Lisp
- value derived from the object passed to @code{translate-to-foreign}
- (@pxref{translate-to-foreign}). This value should be a Lisp number or
- a pointer (satisfies @code{pointerp}), and it can be treated like any
- general Lisp object; it only completes the transformation to a true
- foreign value when passed through low-level code in the Lisp
- implementation, such as the foreign function caller or indirect memory
- addressing combined with a data move.
- In other contexts, this refers to a value accessible by C, but which
- may only be accessed through @cffi{} functions. The closest you can
- get to such a foreign value is through a pointer Lisp object, which
- itself counts as a foreign value in only the previous sense.
- @item simple type
- A @cffi{} type that is ultimately represented as a builtin type;
- @cffi{} only provides extra semantics for Lisp that are invisible to C
- code or data.
- @end table
- @node Comprehensive Index, , Glossary, Top
- @unnumbered Index
- @printindex cp
- @bye
|