0% found this document useful (0 votes)
61 views

Calling C - C++ From Ruby

Ruby c++

Uploaded by

nikola
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
61 views

Calling C - C++ From Ruby

Ruby c++

Uploaded by

nikola
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

7/25/2015

CallingC/C++fromRuby

ThisisablogofAmberBitaRubyonRailswebdevelopmentcompany.Hireusforyourproject!

CallingC/C++fromRuby
2014612

Weoftencometothepoint,whenwehavetowriteenormouslyhugemoduleinRuby.Butwesimply
dontwantto.Maybebecauseweretoolazy/smart,orwedoknowthatsuchlibraryalreadyexists
writteninC/C++.ImplementingpthreadorcryptlibraryinpureRubysoundslikereinventingthe
wheel.TheotherthingiswellwrittenCcodemostlikelywillperformmuchbetterthananyhigher
levelimplementation.Ittakesadvantageofprecompilation,bettergarbagecollectionorstatictyping.
Sowhatshouldwedo?Ifthefunctionalityisrelativelysimple,andwehaveaccesstooriginalsource
code(notonycompled.soor.dllbinaries),firstapproachmaybetogothroughcodelinebylineand
convertit.Whataboutpieceswhichcantbeprocessedinsuchway?Orthealgorithmitselfisvery
complicated?Luckily,thereisafewwaysofcallingCfunctionsfromRubycode.

RubyInline
Itcomesasagem,andrequirestohavegcc/g++compilerinstalled.Afterthatsimplygeminstall
RubyInline.InlineworksbyembeddingpureC/C++codeintoRubycode.Anditdoesntlookcool.
Butwilldothejob,andwilldoitfast.Heresanexampleofcallingpowfunctionfrommathlibrary,as
wellasownimplementationsoffibonacciandfactorialfunctions:
require'inline'
classInlineTest
inlinedo|builder|
builder.include'<math.h>'
builder.c'
intinline_pow(inta,intn){
returnpow(a,n);
}'
builder.c'
longinline_factorial(intmax){
inti=max,result=1;
while(i>=2){result*=i;}
returnresult;
}'
builder.c'
intinline_fibonacci(intn){
inta=1,b=1,c,i;
if(n==0){
return0;
}
for(i=3;i<=n;i++){
c=a+b;
a=b;
b=c;
}
returnb;
}'
https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

1/8

7/25/2015

}'
end
end

CallingC/C++fromRuby

putsInlineTest.new.inline_factorial(5)
putsInlineTest.new.inline_fibonacci(9)
putsInlineTest.new.inline_pow(2,10)

Firstthingwhichcomestomymind,isthatyouactuallyNEEDtowritesomeCcode.Atleastdummy
wrapperofexternalfunction.ItsupportsbothCandC++,andaccordingtoauthors,itsextendableto
workwithotherlanguages.Wedontneedtoworryaboutconversionofpassedargumentsandreturned
data.Alsonomanualcompilationisrequired,itwilldetectanycodechangesandadoptthem.

Rice
Anothergreatsoftware,whichtakescomplicatedC++classes,types,methodsandexposestheminto
Ruby.Thistime,separatedimplementationsarerequired,whichgivesusbetterarrangedproject
structureandmakesitalittlebitmorecomplicatedtosetup.Firstofall,eachclassmethodhastobe
wrappedintoCmethodwithcallsintoRubysAPI.AndheresasimpleexampleofexposingC
functionintoRuby:
#include"rice/Class.hpp"
usingnamespaceRice;
intrice_fibonacci(intn){
inta=1,b=1,c,i;
if(n==0){
return0;
}
for(i=3;i<=n;i++){
c=a+b;
a=b;
b=c;
}
returnb;
}
intrice_factorial(intmax){
inti=max,result=1;
while(i>=2){result*=i;}
returnresult;
}
intrice_pow(inta,intn){
returnpow(a,n);
}
extern"C"
voidInit_rice_test()
{
Classrb_c=define_class("RiceTest")
.define_method("fibonacci",&rice_fibonacci)
.define_method("factorial",&rice_factorial)
.define_method("pow",&rice_pow);
}

BeforewejumptotheRubycode,somepreparationsarerequired.Firststep,installingRicegemgem
installrice.Thenweneedtocreateextconf.rbfilecontaining(orsimplyexecutethecode):
require'mkmfrice'
https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

2/8

7/25/2015

require'mkmfrice'
create_makefile('rice_test')

CallingC/C++fromRuby

RunningthispieceofcodewillgeneratetemplatedMakefile,readytocompilecoderice_test.cpp
classcode.Andfinally,runningmake,whichwillusepregeneratedMakefiletocompileourgluecode
intosharedlibrary.Wewillendupwithrice_test.o(safetoremove)andrice_test.so.Wecando
anythingwithcompiledbinaries:addittoourprojectvendors,oraddtosystemlibraries.Wejustneed
toincludeitinRubycodecorrectlyandcallexposedmethods:
require'./rice_test'
putsRiceTest.new.fibonacci(5)

UsingRicerequiredmorepreparationsthanRubyInline,butwegotcleanersolution,andprecompiled
librariesreadytodroptoapplicationserver.Itprovidesawaytoexposewholeclasses,withalltheir
methods,constructors,attributesaccessorsandsoon.Sothisapproachwouldbebetterifwewantto
takeOOapproach.AlsoRicewasdesignedwithC++inmind,andbecauseofthatwillworkbestwith
C++,butcanbeusedalsotogluepureC.Anotheradvantageisthatwedontneedtohavecompiler
installedonapplicationserver,whichisnice.

FFI
Andlast,butnotleastlibraryImgoingtofocusonisFFI(ForeignFunctionInterface).Asusual,its
availableinformofagem.Althoughithassimplestandmostintuitivedls,itsnotlackingcomplex
functionalities.Greatadvantage(andmaybedisadvantageforsomebodyatthesametime)isthatwe
dontneedtodigintocrazyC/C++interfaceexposing,gluecodegenerationandcodecompilation.As
simpleasthat.SoletscheckFFIinaction.Afterinstallinggeminstallffianditslibraries:libffi
devorlibffideveldependingonyourOS,theonlythingweneedtodoiswrappingsharedlibrary
callsintoRuby:
require'ffi'
moduleFfiMathTest
extendFFI::Library
ffi_lib'c'
ffi_lib'm'
attach_function:pow,[:double,:double],:double
end
putsFfiMathTest.pow(2.2,10)

Definitionsyntaxisselfexplaining,andallthemagichappensinRuby.Theresnointermediate
methodscallingdesiredone.Werejustincludinglibrarieswewanttouse:libcandlibm(math),and
addressingthemwiththeiroriginalname,parameterslistandtypes.AnothersolidpointforFFIisthat
itsmultiplatformandmultiimplementation.ThesamecodewillrunfineonalldifferentRuby
interpreters:MRI,JRuby,RubiniusandallsupportingFFI.Butontheotherhand,itdoesntsupport
C++becauseofthecomplexitythatC++adds,largelytheprobleminvolvedthenamemangling.FFI
includesmanyusefulcomponents,whichincludesinteractionwithCstructures,unions,allocatingand
accessingmemorywithpointersordatatypesmapping.
Andfromcustomlibrarywhichlookslikethis:
#include<stdlib.h>
#include<math.h>
intffi_pow(inta,intn){
returnpow(a,n);
https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

3/8

7/25/2015

CallingC/C++fromRuby

}
intffi_factorial(intmax){
inti=max,result=1;
while(i>=2){result*=i;}
returnresult;
}
intffi_fibonacci(intn){
inta=1,b=1,c,i;
if(n==0){
return0;
}
for(i=3;i<=n;i++){
c=a+b;
a=b;
b=c;
}
returnb;
}

compilation
$gcccfPICffi_test.coffi_test.o
$gccsharedoffi_test.soffi_test.o

Rubybindingandcall:
require'ffi'
moduleFfiCustomTest
extendFFI::Library
ffi_lib'c'
ffi_lib'./ffi_test.so'
attach_function:ffi_pow,[:int,:int],:int
attach_function:ffi_factorial,[:int],:int
attach_function:ffi_fibonacci,[:int],:int
end
putsFfiCustomTest.ffi_factorial(5)
putsFfiCustomTest.ffi_fibonacci(9)
putsFfiCustomTest.ffi_pow(2,10)

Sowhichonetouse?
RubyInlineisextremelyeasytostartwithandallowswrappingCfunctionscallsingluelayer.Itcould
beusefulwhenworkingwithcomplextypes,structuresorclasseswhereasexpectingprimitive
response.RiceinteractsgreatwithC++andallowsOOabstraction.AndFFIbeingabletorunon
variousRubyimplementations.Letslookatsimplebenchmarkofthem,alsowithRubyversion:
defrb_pow(a,n)
a**n
end
defrb_factorial(max)
i=max;result=1
whilei>=2do
result*=i
https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

4/8

7/25/2015

result*=i
i=1
end
result
end

CallingC/C++fromRuby

defrb_fibonacci(n)
a=1;b=1
return0ifn==0
foriin3..ndo
c=a+b
a=b
b=c
end
b
end

Andfinallysomenumbers.100000methodcallsof:factorial(10),fibonacci(20),pow(2,20)

Ruby RubyInline
Rice
FFI
factorial 0.044854815 0.026175138 0.197720523 0.014882004
fibonacci 0.152947962 0.026792521 0.202714029 0.018928646
pow
0.01204131 0.03252452 0.211258897 0.023082315
Asmanyofusmightexpect,FFIperformedbest(withsmallexceptioninpowerfunctionastheresnot
muchcodeandexternalfunctioncallstookmostofthetime).RubyInlinewasanicesurprise.Easyto
startwithcombinedwithgoodperformancemakesitgreatcandidatefornotsodemandingproblems.
ButwhosgonnauseembeddedCcodeforsuchtrivialtasks.Inmostofthecasesitwillbe
mathematicalcalculations.Keepingthatinmind,weshouldprobablyconsiderotherfactors:easyof
useandabilitytoadoptinourproject.

References
https://rubygems.org/gems/RubyInline
https://rubygems.org/gems/rice
https://github.com/ffi/ffi
byKamilDziemianowicz
DoyouneedskilledprofessionalstohelpyoubuildRailsapplications?Hireusforyourproject!

AnnouncingElixirCocktails
Fluxvs.Reflux
Sorcery+GoogleCalendarformultipleusers
https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

5/8

7/25/2015

CallingC/C++fromRuby

Sorcery+GoogleCalendarformultipleusers
Closures:Elixirvs.Rubyvs.JavaScript
SEObasicsforRailsdevelopers
WhyRails5/Turbolinks3.0/ActionCablematter,andwhy@dhhwasrightallalong
5CoolAngularJSlibraries
10skillsthatwillmakeyouabetterRubyist
SplittingmonolithicRailsapplications
Rubythebadparts
CallingC/C++fromRuby
Rubythegoodparts
BuildinganddocumentingAPIinRails
PuttingRubyonRailsonadiet
AutomatetasksonthewebwithRubyandCapybara
PostgreSQLawesomenessforRailsdevelopers
Torquebox3,Rails4zerodowntimedeploymentsonUbuntu12.04
AngularJStemplatesandRubyonRailsassetspipeline
SimilarimagesdetectioninRubyPart1
BuildingsmallsiteswithLocomotiveCMSanddeployingtoHerokuandGridFS
RenderviewsandpartialsoutsidecontrollersinRails3
RubyFLVpseudostreamingimplementedwithSinatraandRack::Evil
MeasuringcomplexityofRuby1.9codewithmetric_abc
GoTranslateYourselfRailsengineformanagingwebsitetranslations
SocialnetworksapplicationdevelopmentwithRailsandOpenSocial(part1introduction)
GeospatialsearchwithRubyandSphinx
IntroductiontoRackmiddleware

7Comments

AmberBitBlog

Share

Recommend 1

Login

SortbyBest

Jointhediscussion

LOGINWITH

ORSIGNUPWITHDISQUS ?

Name
Theldoria ayearago

Iregularlyusethetoolswig(http://www.swig.org/)togenerateaccessfunctions(wrapper
code)toCfunctions,classes,constantsanddatastructuresfromruby.Itworksreliableand
canprovidesnicemeanstowrapallsortsofspecialcases.Anditcangeneratewrapper
codeformanyothertargetlangueslikeluaorpythonaswell.However,itcannotbeused
easily.
Soitisbestsuitedforlargescaleprojectsasanreplacementforrice.
1

Reply Share

ukaszPeszyski ayearago

Goodpostalsocontroversialone:)IhaveusedRiceandinmyopiniontheperformance
differenceshouldnotbethatbig!AlsofactorialwithRiceis4timesslowerthanRuby.There
mustbesomethingwrong,suchthingsshouldnothappen.Checkthatyouhadthesame
https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

6/8

7/25/2015

CallingC/C++fromRuby

mustbesomethingwrong,suchthingsshouldnothappen.Checkthatyouhadthesame
compilerflagsineverycase.Ithinkthatpostbenchmarksthefunctioncallsratherthan
performanceofthefunction.Sometimesfastcallsareneeded,butmostoftenwetryto
delegatesomethingheavylikeaudioprocessing.
WithRice,it'sbiggestadvantageisabilitytowriteobjectorientedcodesoyoucreateaC++
classanditnearlyautomaticallybecomesaclassinRuby.Ithinkyoucanexplorethistopic
inmoredetail,becauseRicetutorialsarenotverypopularontheInternet.
1

Reply Share

KamilDziemianowicz>ukaszPeszyski ayearago

Thanksforthefeedback!WhatiscoolaboutRiceisthatIwasabletopassin/out
complexdatatypeswitharraysetc.Thoughitrequireddefiningbothwaymappingof
allfileds,whichlet'ssayisalittletroublesome...

Reply Share

hubertlepicki ayearago

Cool.Kamil,IhadsometroublebackinthedayswhenIwasforcedtouseC++libraryfrom
FFI.Thetroublewasquiteeasytosolveby...wrappingaroundC++librarycallsintopureC
functions.Didyouexperiencethataswellorwaseverythinggoodinyourcase?
1

Reply Share

KamilDziemianowicz>hubertlepicki ayearago

InfactIdid,triedtouseTopsurfimagedetectionlibraryandhadtowriteRuby
wrapper.AnditendeduponexposingsurfclassmethodsinsimpleCfunctions,
whichwereprettycomplex.SoIgotthatgoinforme,whichisnice:)Probablybetter
examplethanpowerfunction.

Reply Share

CodingMakesYouHappy! 5monthsago

ExcellentwriteuponprettymucheverywaystocallC/C++fromRuby!

Reply Share

RafaelBarbolo ayearago

Thebenchmarksresultsareweird,theyarenotwhatI'dexpect.ButIlikedthecomparisons
intermsofusage.

Reply Share

Wanttogetintouch?Dropusaline!
Yourname...
Youremailaddress...

Yourmessage

https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

7/8

7/25/2015

CallingC/C++fromRuby

Sendyourmessage

Hubertepicki
[email protected]
hubert.lepicki
+48694161264
WojciechPiekutowski
[email protected]
w.piekutowski
+48696152570
About
Blog
Workforus
Rubyprogramming
JavaScriptprogramming
Mobileprogramming
ul.Ksawerw302656Warszawa,Poland
ul.Hetmaska3615727Biaystok,Poland

AmberBit
AmberBitSp.zo.o.jestwpisanadoRejestruPrzedsibiorcwKrajowegoRejestruSdowego
prowadzonegoprzezSdRejonowywBiaymstoku,XIIWydziaGospodarczyKrajowegoRejestru
Sdowego.Kapitazakadowy20000,00zopaconywcaoci.
EUVAT:PL5423228204,NIP:5423228204,KRS:0000439100,REGON:200741641
Weusecookiesonthiswebsiteforanalyticsandtoidentifyuserswhopostcommentsonourblog.
2012AmberBitSp.zo.o.

https://www.amberbit.com/blog/2014/6/12/callingccppfromruby/

8/8

You might also like