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

Calling C - C++ From Ruby

Ruby c++

Uploaded by

nikola
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
67 views

Calling C - C++ From Ruby

Ruby c++

Uploaded by

nikola
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
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
hubert.lepicki@amberbit.com
hubert.lepicki
+48694161264
WojciechPiekutowski
w.piekutowski@amberbit.com
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