csharp.cxx 171 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at https://www.swig.org/legal.html.
  8. *
  9. * csharp.cxx
  10. *
  11. * C# language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. #include "swigmod.h"
  14. #include "cparse.h"
  15. #include <limits.h> // for INT_MAX
  16. #include <ctype.h>
  17. /* Hash type used for upcalls from C/C++ */
  18. typedef DOH UpcallData;
  19. class CSHARP:public Language {
  20. static const char *usage;
  21. const String *empty_string;
  22. const String *public_string;
  23. const String *protected_string;
  24. Hash *swig_types_hash;
  25. File *f_begin;
  26. File *f_runtime;
  27. File *f_runtime_h;
  28. File *f_header;
  29. File *f_wrappers;
  30. File *f_init;
  31. File *f_directors;
  32. File *f_directors_h;
  33. File *f_single_out;
  34. List *filenames_list;
  35. bool proxy_flag; // Flag for generating proxy classes
  36. bool native_function_flag; // Flag for when wrapping a native function
  37. bool enum_constant_flag; // Flag for when wrapping an enum or constant
  38. bool static_flag; // Flag for when wrapping a static functions or member variables
  39. bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
  40. bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
  41. bool global_variable_flag; // Flag for when wrapping a global variable
  42. bool old_variable_names; // Flag for old style variable names in the intermediary class
  43. bool generate_property_declaration_flag; // Flag for generating properties
  44. String *imclass_name; // intermediary class name
  45. String *module_class_name; // module class name
  46. String *imclass_class_code; // intermediary class code
  47. String *proxy_class_def;
  48. String *proxy_class_code;
  49. String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
  50. String *module_class_code;
  51. String *proxy_class_name; // proxy class name
  52. String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
  53. String *variable_name; //Name of a variable being wrapped
  54. String *proxy_class_constants_code;
  55. String *module_class_constants_code;
  56. String *enum_code;
  57. String *dllimport; // DllImport attribute name
  58. String *namespce; // Optional namespace name
  59. String *imclass_imports; //intermediary class imports from %pragma
  60. String *module_imports; //module imports from %pragma
  61. String *imclass_baseclass; //inheritance for intermediary class class from %pragma
  62. String *module_baseclass; //inheritance for module class from %pragma
  63. String *imclass_interfaces; //interfaces for intermediary class class from %pragma
  64. String *module_interfaces; //interfaces for module class from %pragma
  65. String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
  66. String *module_class_modifiers; //class modifiers for module class overridden by %pragma
  67. String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
  68. String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
  69. String *director_callback_typedefs; // Director function pointer typedefs for callbacks
  70. String *director_callbacks; // Director callback function pointer member variables
  71. String *director_delegate_callback; // Director callback method that delegates are set to call
  72. String *director_delegate_definitions; // Director delegates definitions in proxy class
  73. String *director_delegate_instances; // Director delegates member variables in proxy class
  74. String *director_method_types; // Director method types
  75. String *director_connect_parms; // Director delegates parameter list for director connect call
  76. String *destructor_call; //C++ destructor call if any
  77. String *output_file; // File name for single file mode. If set all generated code will be written to this file
  78. // Director method stuff:
  79. List *dmethods_seq;
  80. Hash *dmethods_table;
  81. int n_dmethods;
  82. int n_directors;
  83. int first_class_dmethod;
  84. int curr_class_dmethod;
  85. int nesting_depth;
  86. enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
  87. public:
  88. /* -----------------------------------------------------------------------------
  89. * CSHARP()
  90. * ----------------------------------------------------------------------------- */
  91. CSHARP():empty_string(NewString("")),
  92. public_string(NewString("public")),
  93. protected_string(NewString("protected")),
  94. swig_types_hash(NULL),
  95. f_begin(NULL),
  96. f_runtime(NULL),
  97. f_runtime_h(NULL),
  98. f_header(NULL),
  99. f_wrappers(NULL),
  100. f_init(NULL),
  101. f_directors(NULL),
  102. f_directors_h(NULL),
  103. f_single_out(NULL),
  104. filenames_list(NULL),
  105. proxy_flag(true),
  106. native_function_flag(false),
  107. enum_constant_flag(false),
  108. static_flag(false),
  109. variable_wrapper_flag(false),
  110. wrapping_member_flag(false),
  111. global_variable_flag(false),
  112. old_variable_names(false),
  113. generate_property_declaration_flag(false),
  114. imclass_name(NULL),
  115. module_class_name(NULL),
  116. imclass_class_code(NULL),
  117. proxy_class_def(NULL),
  118. proxy_class_code(NULL),
  119. interface_class_code(NULL),
  120. module_class_code(NULL),
  121. proxy_class_name(NULL),
  122. full_imclass_name(NULL),
  123. variable_name(NULL),
  124. proxy_class_constants_code(NULL),
  125. module_class_constants_code(NULL),
  126. enum_code(NULL),
  127. dllimport(NULL),
  128. namespce(NULL),
  129. imclass_imports(NULL),
  130. module_imports(NULL),
  131. imclass_baseclass(NULL),
  132. module_baseclass(NULL),
  133. imclass_interfaces(NULL),
  134. module_interfaces(NULL),
  135. imclass_class_modifiers(NULL),
  136. module_class_modifiers(NULL),
  137. upcasts_code(NULL),
  138. imclass_cppcasts_code(NULL),
  139. director_callback_typedefs(NULL),
  140. director_callbacks(NULL),
  141. director_delegate_callback(NULL),
  142. director_delegate_definitions(NULL),
  143. director_delegate_instances(NULL),
  144. director_method_types(NULL),
  145. director_connect_parms(NULL),
  146. destructor_call(NULL),
  147. output_file(NULL),
  148. dmethods_seq(NULL),
  149. dmethods_table(NULL),
  150. n_dmethods(0),
  151. n_directors(0),
  152. first_class_dmethod(0),
  153. curr_class_dmethod(0),
  154. nesting_depth(0){
  155. /* for now, multiple inheritance in directors is disabled, this
  156. should be easy to implement though */
  157. director_multiple_inheritance = 0;
  158. director_language = 1;
  159. }
  160. /* -----------------------------------------------------------------------------
  161. * getProxyName()
  162. *
  163. * Test to see if a type corresponds to something wrapped with a proxy class.
  164. * Return NULL if not otherwise the proxy class name, fully qualified with
  165. * a namespace if the nspace feature is used.
  166. * ----------------------------------------------------------------------------- */
  167. String *getProxyName(SwigType *t) {
  168. String *proxyname = NULL;
  169. if (proxy_flag) {
  170. Node *n = classLookup(t);
  171. if (n) {
  172. proxyname = Getattr(n, "proxyname");
  173. if (!proxyname) {
  174. String *nspace = Getattr(n, "sym:nspace");
  175. String *symname = Copy(Getattr(n, "sym:name"));
  176. if (symname && !GetFlag(n, "feature:flatnested")) {
  177. for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
  178. if (String* name = Getattr(outer_class, "sym:name")) {
  179. Push(symname, ".");
  180. Push(symname, name);
  181. }
  182. else
  183. return NULL;
  184. }
  185. }
  186. if (nspace) {
  187. if (namespce)
  188. proxyname = NewStringf("%s.%s.%s", namespce, nspace, symname);
  189. else
  190. proxyname = NewStringf("%s.%s", nspace, symname);
  191. } else {
  192. proxyname = Copy(symname);
  193. }
  194. Setattr(n, "proxyname", proxyname);
  195. Delete(proxyname);
  196. Delete(symname);
  197. }
  198. }
  199. }
  200. return proxyname;
  201. }
  202. /* ------------------------------------------------------------
  203. * main()
  204. * ------------------------------------------------------------ */
  205. virtual void main(int argc, char *argv[]) {
  206. SWIG_library_directory("csharp");
  207. // Look for certain command line options
  208. for (int i = 1; i < argc; i++) {
  209. if (argv[i]) {
  210. if (strcmp(argv[i], "-dllimport") == 0) {
  211. if (argv[i + 1]) {
  212. dllimport = NewString("");
  213. Printf(dllimport, argv[i + 1]);
  214. Swig_mark_arg(i);
  215. Swig_mark_arg(i + 1);
  216. i++;
  217. } else {
  218. Swig_arg_error();
  219. }
  220. } else if (strcmp(argv[i], "-namespace") == 0) {
  221. if (argv[i + 1]) {
  222. namespce = NewString("");
  223. Printf(namespce, argv[i + 1]);
  224. if (Len(namespce) == 0) {
  225. Delete(namespce);
  226. namespce = 0;
  227. }
  228. Swig_mark_arg(i);
  229. Swig_mark_arg(i + 1);
  230. i++;
  231. } else {
  232. Swig_arg_error();
  233. }
  234. } else if ((strcmp(argv[i], "-noproxy") == 0)) {
  235. Swig_mark_arg(i);
  236. proxy_flag = false;
  237. } else if (strcmp(argv[i], "-oldvarnames") == 0) {
  238. Swig_mark_arg(i);
  239. old_variable_names = true;
  240. } else if (strcmp(argv[i], "-outfile") == 0) {
  241. if (argv[i + 1]) {
  242. output_file = NewString("");
  243. Printf(output_file, argv[i + 1]);
  244. Swig_mark_arg(i);
  245. Swig_mark_arg(i + 1);
  246. i++;
  247. } else {
  248. Swig_arg_error();
  249. }
  250. } else if (strcmp(argv[i], "-help") == 0) {
  251. Printf(stdout, "%s\n", usage);
  252. }
  253. }
  254. }
  255. // Add a symbol to the parser for conditional compilation
  256. Preprocessor_define("SWIGCSHARP 1", 0);
  257. // Add typemap definitions
  258. SWIG_typemap_lang("csharp");
  259. SWIG_config_file("csharp.swg");
  260. allow_overloading();
  261. Swig_interface_feature_enable();
  262. }
  263. /* ---------------------------------------------------------------------
  264. * top()
  265. * --------------------------------------------------------------------- */
  266. virtual int top(Node *n) {
  267. // Get any options set in the module directive
  268. Node *optionsnode = Getattr(Getattr(n, "module"), "options");
  269. if (optionsnode) {
  270. if (Getattr(optionsnode, "imclassname"))
  271. imclass_name = Copy(Getattr(optionsnode, "imclassname"));
  272. /* check if directors are enabled for this module. note: this
  273. * is a "master" switch, without which no director code will be
  274. * emitted. %feature("director") statements are also required
  275. * to enable directors for individual classes or methods.
  276. *
  277. * use %module(directors="1") modulename at the start of the
  278. * interface file to enable director generation.
  279. */
  280. if (Getattr(optionsnode, "directors")) {
  281. allow_directors();
  282. }
  283. if (Getattr(optionsnode, "dirprot")) {
  284. allow_dirprot();
  285. }
  286. allow_allprotected(GetFlag(optionsnode, "allprotected"));
  287. }
  288. /* Initialize all of the output files */
  289. String *outfile = Getattr(n, "outfile");
  290. String *outfile_h = Getattr(n, "outfile_h");
  291. if (!outfile) {
  292. Printf(stderr, "Unable to determine outfile\n");
  293. Exit(EXIT_FAILURE);
  294. }
  295. f_begin = NewFile(outfile, "w", SWIG_output_files());
  296. if (!f_begin) {
  297. FileErrorDisplay(outfile);
  298. Exit(EXIT_FAILURE);
  299. }
  300. if (directorsEnabled()) {
  301. if (!outfile_h) {
  302. Printf(stderr, "Unable to determine outfile_h\n");
  303. Exit(EXIT_FAILURE);
  304. }
  305. f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
  306. if (!f_runtime_h) {
  307. FileErrorDisplay(outfile_h);
  308. Exit(EXIT_FAILURE);
  309. }
  310. }
  311. f_runtime = NewString("");
  312. f_init = NewString("");
  313. f_header = NewString("");
  314. f_wrappers = NewString("");
  315. f_directors_h = NewString("");
  316. f_directors = NewString("");
  317. /* Register file targets with the SWIG file handler */
  318. Swig_register_filebyname("header", f_header);
  319. Swig_register_filebyname("wrapper", f_wrappers);
  320. Swig_register_filebyname("begin", f_begin);
  321. Swig_register_filebyname("runtime", f_runtime);
  322. Swig_register_filebyname("init", f_init);
  323. Swig_register_filebyname("director", f_directors);
  324. Swig_register_filebyname("director_h", f_directors_h);
  325. swig_types_hash = NewHash();
  326. filenames_list = NewList();
  327. // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
  328. if (!imclass_name) {
  329. imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
  330. module_class_name = Copy(Getattr(n, "name"));
  331. } else {
  332. // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
  333. if (Cmp(imclass_name, Getattr(n, "name")) == 0)
  334. module_class_name = NewStringf("%sModule", Getattr(n, "name"));
  335. else
  336. module_class_name = Copy(Getattr(n, "name"));
  337. }
  338. // module class and intermediary classes are always created
  339. if (!addSymbol(imclass_name, n))
  340. return SWIG_ERROR;
  341. if (!addSymbol(module_class_name, n))
  342. return SWIG_ERROR;
  343. imclass_class_code = NewString("");
  344. proxy_class_def = NewString("");
  345. proxy_class_code = NewString("");
  346. module_class_constants_code = NewString("");
  347. imclass_baseclass = NewString("");
  348. imclass_interfaces = NewString("");
  349. imclass_class_modifiers = NewString("");
  350. module_class_code = NewString("");
  351. module_baseclass = NewString("");
  352. module_interfaces = NewString("");
  353. module_imports = NewString("");
  354. module_class_modifiers = NewString("");
  355. imclass_imports = NewString("");
  356. imclass_cppcasts_code = NewString("");
  357. director_connect_parms = NewString("");
  358. upcasts_code = NewString("");
  359. dmethods_seq = NewList();
  360. dmethods_table = NewHash();
  361. n_dmethods = 0;
  362. n_directors = 0;
  363. if (!dllimport)
  364. dllimport = Copy(module_class_name);
  365. Swig_banner(f_begin);
  366. Swig_obligatory_macros(f_runtime, "CSHARP");
  367. if (directorsEnabled()) {
  368. Printf(f_runtime, "#define SWIG_DIRECTORS\n");
  369. /* Emit initial director header and director code: */
  370. Swig_banner(f_directors_h);
  371. Printf(f_directors_h, "\n");
  372. Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
  373. Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
  374. Printf(f_directors, "\n\n");
  375. Printf(f_directors, "/* ---------------------------------------------------\n");
  376. Printf(f_directors, " * C++ director class methods\n");
  377. Printf(f_directors, " * --------------------------------------------------- */\n\n");
  378. if (outfile_h) {
  379. String *filename = Swig_file_filename(outfile_h);
  380. Printf(f_directors, "#include \"%s\"\n\n", filename);
  381. Delete(filename);
  382. }
  383. }
  384. Printf(f_runtime, "\n");
  385. if (namespce) {
  386. String *wrapper_name = NewStringf("");
  387. Printf(wrapper_name, "CSharp_%s_%%f", namespce);
  388. Swig_name_register("wrapper", wrapper_name);
  389. Delete(wrapper_name);
  390. }
  391. else {
  392. Swig_name_register("wrapper", "CSharp_%f");
  393. }
  394. if (old_variable_names) {
  395. Swig_name_register("set", "set_%n%v");
  396. Swig_name_register("get", "get_%n%v");
  397. }
  398. Printf(f_wrappers, "\n#ifdef __cplusplus\n");
  399. Printf(f_wrappers, "extern \"C\" {\n");
  400. Printf(f_wrappers, "#endif\n\n");
  401. /* Emit code */
  402. Language::top(n);
  403. if (directorsEnabled()) {
  404. // Insert director runtime into the f_runtime file (make it occur before %header section)
  405. Swig_insert_file("director_common.swg", f_runtime);
  406. Swig_insert_file("director.swg", f_runtime);
  407. }
  408. // Generate the intermediary class
  409. {
  410. File *f_im = getOutputFile(SWIG_output_directory(), imclass_name);
  411. addOpenNamespace(0, f_im);
  412. if (imclass_imports)
  413. Printf(f_im, "%s\n", imclass_imports);
  414. if (Len(imclass_class_modifiers) > 0)
  415. Printf(f_im, "%s ", imclass_class_modifiers);
  416. Printf(f_im, "%s ", imclass_name);
  417. if (imclass_baseclass && *Char(imclass_baseclass))
  418. Printf(f_im, ": %s ", imclass_baseclass);
  419. if (Len(imclass_interfaces) > 0)
  420. Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
  421. Printf(f_im, "{\n");
  422. // Add the intermediary class methods
  423. Replaceall(imclass_class_code, "$module", module_class_name);
  424. Replaceall(imclass_class_code, "$imclassname", imclass_name);
  425. Replaceall(imclass_class_code, "$dllimport", dllimport);
  426. Printv(f_im, imclass_class_code, NIL);
  427. Printv(f_im, imclass_cppcasts_code, NIL);
  428. // Finish off the class
  429. Printf(f_im, "}\n");
  430. addCloseNamespace(0, f_im);
  431. if (f_im != f_single_out)
  432. Delete(f_im);
  433. f_im = NULL;
  434. }
  435. // Generate the C# module class
  436. {
  437. File *f_module = getOutputFile(SWIG_output_directory(), module_class_name);
  438. addOpenNamespace(0, f_module);
  439. if (module_imports)
  440. Printf(f_module, "%s\n", module_imports);
  441. if (Len(module_class_modifiers) > 0)
  442. Printf(f_module, "%s ", module_class_modifiers);
  443. Printf(f_module, "%s ", module_class_name);
  444. if (module_baseclass && *Char(module_baseclass))
  445. Printf(f_module, ": %s ", module_baseclass);
  446. if (Len(module_interfaces) > 0)
  447. Printv(f_module, "implements ", module_interfaces, " ", NIL);
  448. Printf(f_module, "{\n");
  449. Replaceall(module_class_code, "$module", module_class_name);
  450. Replaceall(module_class_constants_code, "$module", module_class_name);
  451. Replaceall(module_class_code, "$imclassname", imclass_name);
  452. Replaceall(module_class_constants_code, "$imclassname", imclass_name);
  453. Replaceall(module_class_code, "$dllimport", dllimport);
  454. Replaceall(module_class_constants_code, "$dllimport", dllimport);
  455. // Add the wrapper methods
  456. Printv(f_module, module_class_code, NIL);
  457. // Write out all the global constants
  458. Printv(f_module, module_class_constants_code, NIL);
  459. // Finish off the class
  460. Printf(f_module, "}\n");
  461. addCloseNamespace(0, f_module);
  462. if (f_module != f_single_out)
  463. Delete(f_module);
  464. f_module = NULL;
  465. }
  466. if (upcasts_code)
  467. Printv(f_wrappers, upcasts_code, NIL);
  468. Printf(f_wrappers, "#ifdef __cplusplus\n");
  469. Printf(f_wrappers, "}\n");
  470. Printf(f_wrappers, "#endif\n");
  471. // Output a C# type wrapper class for each SWIG type
  472. for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
  473. emitTypeWrapperClass(swig_type.key, swig_type.item);
  474. }
  475. // Check for overwriting file problems on filesystems that are case insensitive
  476. Iterator it1;
  477. Iterator it2;
  478. for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
  479. String *item1_lower = Swig_string_lower(it1.item);
  480. for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
  481. String *item2_lower = Swig_string_lower(it2.item);
  482. if (it1.item && it2.item) {
  483. if (Strcmp(item1_lower, item2_lower) == 0) {
  484. Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
  485. "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
  486. "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
  487. }
  488. }
  489. Delete(item2_lower);
  490. }
  491. Delete(item1_lower);
  492. }
  493. Delete(swig_types_hash);
  494. swig_types_hash = NULL;
  495. Delete(filenames_list);
  496. filenames_list = NULL;
  497. Delete(imclass_name);
  498. imclass_name = NULL;
  499. Delete(imclass_class_code);
  500. imclass_class_code = NULL;
  501. Delete(proxy_class_def);
  502. proxy_class_def = NULL;
  503. Delete(proxy_class_code);
  504. proxy_class_code = NULL;
  505. Delete(module_class_constants_code);
  506. module_class_constants_code = NULL;
  507. Delete(imclass_baseclass);
  508. imclass_baseclass = NULL;
  509. Delete(imclass_interfaces);
  510. imclass_interfaces = NULL;
  511. Delete(imclass_class_modifiers);
  512. imclass_class_modifiers = NULL;
  513. Delete(module_class_name);
  514. module_class_name = NULL;
  515. Delete(module_class_code);
  516. module_class_code = NULL;
  517. Delete(module_baseclass);
  518. module_baseclass = NULL;
  519. Delete(module_interfaces);
  520. module_interfaces = NULL;
  521. Delete(module_imports);
  522. module_imports = NULL;
  523. Delete(module_class_modifiers);
  524. module_class_modifiers = NULL;
  525. Delete(imclass_imports);
  526. imclass_imports = NULL;
  527. Delete(imclass_cppcasts_code);
  528. imclass_cppcasts_code = NULL;
  529. Delete(upcasts_code);
  530. upcasts_code = NULL;
  531. Delete(dmethods_seq);
  532. dmethods_seq = NULL;
  533. Delete(dmethods_table);
  534. dmethods_table = NULL;
  535. Delete(namespce);
  536. namespce = NULL;
  537. n_dmethods = 0;
  538. /* Close all of the files */
  539. Dump(f_runtime, f_begin);
  540. Dump(f_header, f_begin);
  541. if (directorsEnabled()) {
  542. Dump(f_directors, f_begin);
  543. Dump(f_directors_h, f_runtime_h);
  544. Printf(f_runtime_h, "\n");
  545. Printf(f_runtime_h, "#endif\n");
  546. Delete(f_runtime_h);
  547. f_runtime_h = NULL;
  548. Delete(f_directors);
  549. f_directors = NULL;
  550. Delete(f_directors_h);
  551. f_directors_h = NULL;
  552. }
  553. if (f_single_out) {
  554. Dump(f_single_out, f_begin);
  555. Delete(f_single_out);
  556. f_single_out = NULL;
  557. }
  558. Dump(f_wrappers, f_begin);
  559. Wrapper_pretty_print(f_init, f_begin);
  560. Delete(f_header);
  561. Delete(f_wrappers);
  562. Delete(f_init);
  563. Delete(f_runtime);
  564. Delete(f_begin);
  565. return SWIG_OK;
  566. }
  567. /* -----------------------------------------------------------------------------
  568. * emitBanner()
  569. * ----------------------------------------------------------------------------- */
  570. void emitBanner(File *f) {
  571. Printf(f, "//------------------------------------------------------------------------------\n");
  572. Printf(f, "// <auto-generated />\n");
  573. Printf(f, "//\n");
  574. Swig_banner_target_lang(f, "//");
  575. Printf(f, "//------------------------------------------------------------------------------\n\n");
  576. }
  577. /* -----------------------------------------------------------------------------
  578. * getOutputFile()
  579. *
  580. * Prepares a File object by creating the file in the file system and
  581. * writing the banner for auto-generated files to it (emitBanner).
  582. * If '-outfile' is provided (single file mode) the supplied parameters will
  583. * be ignored and the returned file will always be:
  584. * <outdir>/<outfile>
  585. * Otherwise the file will be:
  586. * <dir>/<name>.cs
  587. * ----------------------------------------------------------------------------- */
  588. File *getOutputFile(const String *dir, const String *name) {
  589. if (output_file) {
  590. if (!f_single_out) {
  591. String *filen = NewStringf("%s%s", SWIG_output_directory(), output_file);
  592. f_single_out = NewFile(filen, "w", SWIG_output_files());
  593. if (!f_single_out) {
  594. FileErrorDisplay(filen);
  595. Exit(EXIT_FAILURE);
  596. }
  597. Append(filenames_list, Copy(filen));
  598. Delete(filen);
  599. filen = NULL;
  600. emitBanner(f_single_out);
  601. }
  602. return f_single_out;
  603. } else {
  604. String *filen = NewStringf("%s%s.cs", dir, name);
  605. File *f = NewFile(filen, "w", SWIG_output_files());
  606. if (!f) {
  607. FileErrorDisplay(filen);
  608. Exit(EXIT_FAILURE);
  609. }
  610. Append(filenames_list, Copy(filen));
  611. Delete(filen);
  612. filen = NULL;
  613. emitBanner(f);
  614. return f;
  615. }
  616. }
  617. /*-----------------------------------------------------------------------
  618. * Add new director upcall signature
  619. *----------------------------------------------------------------------*/
  620. UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
  621. String *key = NewStringf("%s|%s", imclass_method, decl);
  622. ++curr_class_dmethod;
  623. String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
  624. n_dmethods++;
  625. Hash *new_udata = NewHash();
  626. Append(dmethods_seq, new_udata);
  627. Setattr(dmethods_table, key, new_udata);
  628. Setattr(new_udata, "method", Copy(class_method));
  629. Setattr(new_udata, "class_methodidx", class_methodidx);
  630. Setattr(new_udata, "decl", Copy(decl));
  631. Setattr(new_udata, "overname", Copy(overloaded_name));
  632. Delete(key);
  633. return new_udata;
  634. }
  635. /*-----------------------------------------------------------------------
  636. * Get director upcall signature
  637. *----------------------------------------------------------------------*/
  638. /*
  639. UpcallData * getUpcallMethodData(String *director_class, String *decl) {
  640. String *key = NewStringf("%s|%s", director_class, decl);
  641. UpcallData *udata = Getattr(dmethods_table, key);
  642. Delete(key);
  643. return udata;
  644. }
  645. */
  646. /* ----------------------------------------------------------------------
  647. * nativeWrapper()
  648. * ---------------------------------------------------------------------- */
  649. virtual int nativeWrapper(Node *n) {
  650. String *wrapname = Getattr(n, "wrap:name");
  651. if (!addSymbol(wrapname, n, imclass_name))
  652. return SWIG_ERROR;
  653. if (Getattr(n, "type")) {
  654. Swig_save("nativeWrapper", n, "name", NIL);
  655. Setattr(n, "name", wrapname);
  656. native_function_flag = true;
  657. functionWrapper(n);
  658. Swig_restore(n);
  659. native_function_flag = false;
  660. } else {
  661. Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
  662. }
  663. return SWIG_OK;
  664. }
  665. /* ----------------------------------------------------------------------
  666. * functionWrapper()
  667. * ---------------------------------------------------------------------- */
  668. virtual int functionWrapper(Node *n) {
  669. String *symname = Getattr(n, "sym:name");
  670. SwigType *t = Getattr(n, "type");
  671. ParmList *l = Getattr(n, "parms");
  672. String *tm;
  673. Parm *p;
  674. int i;
  675. String *c_return_type = NewString("");
  676. String *im_return_type = NewString("");
  677. String *cleanup = NewString("");
  678. String *outarg = NewString("");
  679. String *body = NewString("");
  680. String *im_outattributes = 0;
  681. int num_arguments = 0;
  682. bool is_void_return;
  683. String *overloaded_name = getOverloadedName(n);
  684. if (!Getattr(n, "sym:overloaded")) {
  685. if (!addSymbol(symname, n, imclass_name))
  686. return SWIG_ERROR;
  687. }
  688. /*
  689. The rest of this function deals with generating the intermediary class wrapper function (that wraps
  690. a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
  691. matching PInvoke c function call.
  692. */
  693. // A new wrapper function object
  694. Wrapper *f = NewWrapper();
  695. // Make a wrapper name for this function
  696. String *wname = Swig_name_wrapper(overloaded_name);
  697. /* Attach the non-standard typemaps to the parameter list. */
  698. Swig_typemap_attach_parms("ctype", l, f);
  699. Swig_typemap_attach_parms("imtype", l, f);
  700. /* Get return types */
  701. if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
  702. String *ctypeout = Getattr(n, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
  703. if (ctypeout)
  704. tm = ctypeout;
  705. Printf(c_return_type, "%s", tm);
  706. } else {
  707. Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0));
  708. }
  709. if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
  710. String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
  711. if (imtypeout)
  712. tm = imtypeout;
  713. Printf(im_return_type, "%s", tm);
  714. im_outattributes = Getattr(n, "tmap:imtype:outattributes");
  715. } else {
  716. Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
  717. }
  718. is_void_return = (Cmp(c_return_type, "void") == 0);
  719. if (!is_void_return)
  720. Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
  721. Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
  722. // Emit all of the local variables for holding arguments.
  723. emit_parameter_variables(l, f);
  724. /* Attach the standard typemaps */
  725. emit_attach_parmmaps(l, f);
  726. // Parameter overloading
  727. Setattr(n, "wrap:parms", l);
  728. Setattr(n, "wrap:name", wname);
  729. // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
  730. if (Getattr(n, "sym:overloaded")) {
  731. // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
  732. Swig_overload_check(n);
  733. if (Getattr(n, "overload:ignore")) {
  734. DelWrapper(f);
  735. return SWIG_OK;
  736. }
  737. }
  738. Printv(imclass_class_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
  739. if (im_outattributes)
  740. Printf(imclass_class_code, " %s\n", im_outattributes);
  741. Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
  742. /* Get number of required and total arguments */
  743. num_arguments = emit_num_arguments(l);
  744. int gencomma = 0;
  745. // Now walk the function parameter list and generate code to get arguments
  746. for (i = 0, p = l; i < num_arguments; i++) {
  747. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  748. p = Getattr(p, "tmap:in:next");
  749. }
  750. SwigType *pt = Getattr(p, "type");
  751. String *ln = Getattr(p, "lname");
  752. String *im_param_type = NewString("");
  753. String *c_param_type = NewString("");
  754. String *arg = NewString("");
  755. Printf(arg, "j%s", ln);
  756. /* Get the ctype types of the parameter */
  757. if ((tm = Getattr(p, "tmap:ctype"))) {
  758. Printv(c_param_type, tm, NIL);
  759. } else {
  760. Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
  761. }
  762. /* Get the intermediary class parameter types of the parameter */
  763. if ((tm = Getattr(p, "tmap:imtype"))) {
  764. const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
  765. Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  766. } else {
  767. Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
  768. }
  769. /* Add parameter to intermediary class method */
  770. if (gencomma)
  771. Printf(imclass_class_code, ", ");
  772. Printf(imclass_class_code, "%s %s", im_param_type, arg);
  773. // Add parameter to C function
  774. Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
  775. gencomma = 1;
  776. // Get typemap for this argument
  777. if ((tm = Getattr(p, "tmap:in"))) {
  778. canThrow(n, "in", p);
  779. Replaceall(tm, "$arg", arg); /* deprecated? */
  780. Replaceall(tm, "$input", arg);
  781. Setattr(p, "emit:input", arg);
  782. Printf(f->code, "%s\n", tm);
  783. p = Getattr(p, "tmap:in:next");
  784. } else {
  785. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  786. p = nextSibling(p);
  787. }
  788. Delete(im_param_type);
  789. Delete(c_param_type);
  790. Delete(arg);
  791. }
  792. /* Insert constraint checking code */
  793. for (p = l; p;) {
  794. if ((tm = Getattr(p, "tmap:check"))) {
  795. canThrow(n, "check", p);
  796. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  797. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  798. Printv(f->code, tm, "\n", NIL);
  799. p = Getattr(p, "tmap:check:next");
  800. } else {
  801. p = nextSibling(p);
  802. }
  803. }
  804. /* Insert cleanup code */
  805. for (p = l; p;) {
  806. if ((tm = Getattr(p, "tmap:freearg"))) {
  807. canThrow(n, "freearg", p);
  808. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  809. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  810. Printv(cleanup, tm, "\n", NIL);
  811. p = Getattr(p, "tmap:freearg:next");
  812. } else {
  813. p = nextSibling(p);
  814. }
  815. }
  816. /* Insert argument output code */
  817. for (p = l; p;) {
  818. if ((tm = Getattr(p, "tmap:argout"))) {
  819. canThrow(n, "argout", p);
  820. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  821. Replaceall(tm, "$result", "jresult");
  822. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  823. Printv(outarg, tm, "\n", NIL);
  824. p = Getattr(p, "tmap:argout:next");
  825. } else {
  826. p = nextSibling(p);
  827. }
  828. }
  829. // Look for usage of throws typemap and the canthrow flag
  830. ParmList *throw_parm_list = NULL;
  831. if ((throw_parm_list = Getattr(n, "catchlist"))) {
  832. Swig_typemap_attach_parms("throws", throw_parm_list, f);
  833. for (p = throw_parm_list; p; p = nextSibling(p)) {
  834. if (Getattr(p, "tmap:throws")) {
  835. canThrow(n, "throws", p);
  836. }
  837. }
  838. }
  839. String *null_attribute = 0;
  840. // Now write code to make the function call
  841. if (!native_function_flag) {
  842. Swig_director_emit_dynamic_cast(n, f);
  843. String *actioncode = emit_action(n);
  844. /* Return value if necessary */
  845. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  846. canThrow(n, "out", n);
  847. Replaceall(tm, "$result", "jresult");
  848. if (GetFlag(n, "feature:new"))
  849. Replaceall(tm, "$owner", "1");
  850. else
  851. Replaceall(tm, "$owner", "0");
  852. Printf(f->code, "%s", tm);
  853. null_attribute = Getattr(n, "tmap:out:null");
  854. if (Len(tm))
  855. Printf(f->code, "\n");
  856. } else {
  857. Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
  858. }
  859. emit_return_variable(n, t, f);
  860. }
  861. /* Output argument output code */
  862. Printv(f->code, outarg, NIL);
  863. /* Output cleanup code */
  864. Printv(f->code, cleanup, NIL);
  865. /* Look to see if there is any newfree cleanup code */
  866. if (GetFlag(n, "feature:new")) {
  867. if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
  868. canThrow(n, "newfree", n);
  869. Printf(f->code, "%s\n", tm);
  870. }
  871. }
  872. /* See if there is any return cleanup code */
  873. if (!native_function_flag) {
  874. if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
  875. canThrow(n, "ret", n);
  876. Printf(f->code, "%s\n", tm);
  877. }
  878. }
  879. /* Finish C function and intermediary class function definitions */
  880. Printf(imclass_class_code, ")");
  881. Printf(imclass_class_code, ";\n");
  882. Printf(f->def, ") {");
  883. if (!is_void_return)
  884. Printv(f->code, " return jresult;\n", NIL);
  885. Printf(f->code, "}\n");
  886. /* Substitute the cleanup code */
  887. Replaceall(f->code, "$cleanup", cleanup);
  888. /* Substitute the function name */
  889. Replaceall(f->code, "$symname", symname);
  890. /* Contract macro modification */
  891. if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
  892. Setattr(n, "csharp:canthrow", "1");
  893. }
  894. if (!null_attribute)
  895. Replaceall(f->code, "$null", "0");
  896. else
  897. Replaceall(f->code, "$null", null_attribute);
  898. /* Dump the function out */
  899. if (!native_function_flag) {
  900. Wrapper_print(f, f_wrappers);
  901. // Handle %csexception which sets the canthrow attribute
  902. if (Getattr(n, "feature:except:canthrow"))
  903. Setattr(n, "csharp:canthrow", "1");
  904. // A very simple check (it is not foolproof) to help typemap/feature writers for
  905. // throwing C# exceptions from unmanaged code. It checks for the common methods which
  906. // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
  907. // so that code which checks for pending exceptions is added in the C# proxy method.
  908. if (!Getattr(n, "csharp:canthrow")) {
  909. if (Strstr(f->code, "SWIG_exception")) {
  910. Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
  911. "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
  912. } else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
  913. Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
  914. "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
  915. }
  916. }
  917. }
  918. if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
  919. moduleClassFunctionHandler(n);
  920. }
  921. /*
  922. * Generate the proxy class properties for public member variables.
  923. * Not for enums and constants.
  924. */
  925. if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
  926. // Capitalize the first letter in the variable in the getter/setter function name
  927. bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
  928. String *getter_setter_name = NewString("");
  929. if (!getter_flag)
  930. Printf(getter_setter_name, "set");
  931. else
  932. Printf(getter_setter_name, "get");
  933. Putc(toupper((int) *Char(variable_name)), getter_setter_name);
  934. Printf(getter_setter_name, "%s", Char(variable_name) + 1);
  935. Setattr(n, "proxyfuncname", getter_setter_name);
  936. Setattr(n, "imfuncname", symname);
  937. proxyClassFunctionHandler(n);
  938. Delete(getter_setter_name);
  939. }
  940. Delete(c_return_type);
  941. Delete(im_return_type);
  942. Delete(cleanup);
  943. Delete(outarg);
  944. Delete(body);
  945. Delete(overloaded_name);
  946. DelWrapper(f);
  947. return SWIG_OK;
  948. }
  949. /* -----------------------------------------------------------------------
  950. * variableWrapper()
  951. * ----------------------------------------------------------------------- */
  952. virtual int variableWrapper(Node *n) {
  953. Language::variableWrapper(n);
  954. return SWIG_OK;
  955. }
  956. /* -----------------------------------------------------------------------
  957. * globalvariableHandler()
  958. * ------------------------------------------------------------------------ */
  959. virtual int globalvariableHandler(Node *n) {
  960. generate_property_declaration_flag = true;
  961. variable_name = Getattr(n, "sym:name");
  962. global_variable_flag = true;
  963. int ret = Language::globalvariableHandler(n);
  964. global_variable_flag = false;
  965. generate_property_declaration_flag = false;
  966. if (proxy_flag) {
  967. Printf(module_class_code, "\n }\n\n");
  968. }
  969. return ret;
  970. }
  971. String *getCurrentScopeName(String *nspace) {
  972. String *scope = 0;
  973. if (nspace || getCurrentClass()) {
  974. scope = NewString("");
  975. if (nspace)
  976. Printf(scope, "%s", nspace);
  977. if (Node *cls = getCurrentClass()) {
  978. if (Node *outer = Getattr(cls, "nested:outer")) {
  979. String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
  980. for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
  981. Push(outerClassesPrefix, ".");
  982. Push(outerClassesPrefix, Getattr(outer, "sym:name"));
  983. }
  984. Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
  985. Delete(outerClassesPrefix);
  986. } else
  987. Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
  988. }
  989. }
  990. return scope;
  991. }
  992. /* ----------------------------------------------------------------------
  993. * enumDeclaration()
  994. *
  995. * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
  996. * 1) Simple enums - simple constant within the proxy class or module class
  997. * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
  998. * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
  999. * 4) Proper enums - proper C# enum
  1000. * Anonymous enums always default to 1)
  1001. * ---------------------------------------------------------------------- */
  1002. virtual int enumDeclaration(Node *n) {
  1003. if (!ImportMode) {
  1004. if (getCurrentClass() && (cplus_mode != PUBLIC))
  1005. return SWIG_NOWRAP;
  1006. String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
  1007. if (proxy_flag && !is_wrapping_class()) {
  1008. // Global enums / enums in a namespace
  1009. assert(!full_imclass_name);
  1010. if (!nspace) {
  1011. full_imclass_name = NewStringf("%s", imclass_name);
  1012. } else {
  1013. if (namespce) {
  1014. full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
  1015. } else {
  1016. full_imclass_name = NewStringf("%s", imclass_name);
  1017. }
  1018. }
  1019. }
  1020. enum_code = NewString("");
  1021. String *symname = Getattr(n, "sym:name");
  1022. String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
  1023. EnumFeature enum_feature = decodeEnumFeature(n);
  1024. String *typemap_lookup_type = Getattr(n, "name");
  1025. if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
  1026. // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
  1027. String *scope = getCurrentScopeName(nspace);
  1028. if (!addSymbol(symname, n, scope))
  1029. return SWIG_ERROR;
  1030. // Pure C# baseclass and interfaces
  1031. const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE);
  1032. const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE);
  1033. // Class attributes
  1034. const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
  1035. if (csattributes && *Char(csattributes))
  1036. Printf(enum_code, "%s\n", csattributes);
  1037. // Emit the enum
  1038. Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
  1039. " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
  1040. ", " : "", pure_interfaces, " {\n", NIL);
  1041. Delete(scope);
  1042. } else {
  1043. // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
  1044. if (symname && !Getattr(n, "unnamedinstance"))
  1045. Printf(constants_code, " // %s \n", symname);
  1046. }
  1047. // Emit each enum item
  1048. Language::enumDeclaration(n);
  1049. if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
  1050. // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
  1051. // Finish the enum declaration
  1052. // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
  1053. Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
  1054. typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
  1055. "}", NIL);
  1056. Replaceall(enum_code, "$csclassname", symname);
  1057. // Substitute $enumvalues - intended usage is for typesafe enums
  1058. if (Getattr(n, "enumvalues"))
  1059. Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
  1060. else
  1061. Replaceall(enum_code, "$enumvalues", "");
  1062. if (proxy_flag && is_wrapping_class()) {
  1063. // Enums defined within the C++ class are defined within the proxy class
  1064. // Add extra indentation
  1065. Replaceall(enum_code, "\n", "\n ");
  1066. Replaceall(enum_code, " \n", "\n");
  1067. Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
  1068. } else {
  1069. // Global enums are defined in their own file
  1070. String *output_directory = outputDirectory(nspace);
  1071. File *f_enum = getOutputFile(output_directory, symname);
  1072. addOpenNamespace(nspace, f_enum);
  1073. Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
  1074. "\n", enum_code, "\n", NIL);
  1075. addCloseNamespace(nspace, f_enum);
  1076. if (f_enum != f_single_out)
  1077. Delete(f_enum);
  1078. f_enum = NULL;
  1079. Delete(output_directory);
  1080. }
  1081. } else {
  1082. // Wrap C++ enum with simple constant
  1083. Printf(enum_code, "\n");
  1084. if (proxy_flag && is_wrapping_class())
  1085. Printv(proxy_class_constants_code, enum_code, NIL);
  1086. else
  1087. Printv(module_class_constants_code, enum_code, NIL);
  1088. }
  1089. Delete(enum_code);
  1090. enum_code = NULL;
  1091. if (proxy_flag && !is_wrapping_class()) {
  1092. Delete(full_imclass_name);
  1093. full_imclass_name = 0;
  1094. }
  1095. }
  1096. return SWIG_OK;
  1097. }
  1098. /* ----------------------------------------------------------------------
  1099. * enumvalueDeclaration()
  1100. * ---------------------------------------------------------------------- */
  1101. virtual int enumvalueDeclaration(Node *n) {
  1102. if (getCurrentClass() && (cplus_mode != PUBLIC))
  1103. return SWIG_NOWRAP;
  1104. Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
  1105. String *symname = Getattr(n, "sym:name");
  1106. String *value = Getattr(n, "value");
  1107. String *name = Getattr(n, "name");
  1108. Node *parent = parentNode(n);
  1109. int unnamedinstance = GetFlag(parent, "unnamedinstance");
  1110. String *parent_name = Getattr(parent, "name");
  1111. String *nspace = getNSpace();
  1112. String *newsymname = 0;
  1113. String *tmpValue;
  1114. // Strange hack from parent method
  1115. if (value)
  1116. tmpValue = NewString(value);
  1117. else
  1118. tmpValue = NewString(name);
  1119. // Note that this is used in enumValue() amongst other places
  1120. Setattr(n, "value", tmpValue);
  1121. // Deal with enum values that are not int
  1122. int swigtype = SwigType_type(Getattr(n, "type"));
  1123. if (swigtype == T_BOOL) {
  1124. const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
  1125. Setattr(n, "enumvalue", val);
  1126. } else if (swigtype == T_CHAR) {
  1127. String *val = NewStringf("'%(hexescape)s'", Getattr(n, "enumvalue"));
  1128. Setattr(n, "enumvalue", val);
  1129. Delete(val);
  1130. }
  1131. {
  1132. EnumFeature enum_feature = decodeEnumFeature(parent);
  1133. if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
  1134. newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
  1135. symname = newsymname;
  1136. }
  1137. // Add to language symbol table
  1138. String *scope = 0;
  1139. if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
  1140. String *enumClassPrefix = getEnumClassPrefix();
  1141. if (enumClassPrefix) {
  1142. scope = NewString("");
  1143. if (nspace)
  1144. Printf(scope, "%s.", nspace);
  1145. Printf(scope, "%s", enumClassPrefix);
  1146. } else {
  1147. scope = Copy(module_class_name);
  1148. }
  1149. } else {
  1150. scope = getCurrentScopeName(nspace);
  1151. if (!scope)
  1152. scope = Copy(Getattr(parent, "sym:name"));
  1153. else
  1154. Printf(scope, ".%s", Getattr(parent, "sym:name"));
  1155. }
  1156. if (!addSymbol(symname, n, scope))
  1157. return SWIG_ERROR;
  1158. const String *csattributes = Getattr(n, "feature:cs:attributes");
  1159. if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
  1160. // Wrap (non-anonymous) C/C++ enum with a proper C# enum
  1161. // Emit the enum item.
  1162. if (!GetFlag(n, "firstenumitem"))
  1163. Printf(enum_code, ",\n");
  1164. if (csattributes)
  1165. Printf(enum_code, " %s\n", csattributes);
  1166. Printf(enum_code, " %s", symname);
  1167. // Check for the %csconstvalue feature
  1168. String *value = Getattr(n, "feature:cs:constvalue");
  1169. // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
  1170. value = value ? value : Getattr(n, "enumvalue");
  1171. if (value) {
  1172. Printf(enum_code, " = %s", value);
  1173. }
  1174. } else {
  1175. // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
  1176. SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
  1177. Setattr(n, "type", typemap_lookup_type);
  1178. const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF);
  1179. String *return_type = Copy(tm);
  1180. substituteClassname(typemap_lookup_type, return_type);
  1181. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  1182. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  1183. if (csattributes)
  1184. Printf(enum_code, " %s\n", csattributes);
  1185. if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
  1186. // Wrap (non-anonymous) enum using the typesafe enum pattern
  1187. if (Getattr(n, "enumvalue")) {
  1188. String *value = enumValue(n);
  1189. Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
  1190. Delete(value);
  1191. } else {
  1192. Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
  1193. }
  1194. } else {
  1195. // Simple integer constants
  1196. // Note these are always generated for anonymous enums, no matter what enum_feature is specified
  1197. // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
  1198. // The %csconst feature determines how the constant value is obtained
  1199. int const_feature_flag = GetFlag(n, "feature:cs:const");
  1200. const char *const_readonly = const_feature_flag ? "const" : "static readonly";
  1201. String *value = enumValue(n);
  1202. Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
  1203. Delete(value);
  1204. }
  1205. Delete(return_type);
  1206. }
  1207. // Add the enum value to the comma separated list being constructed in the enum declaration.
  1208. String *enumvalues = Getattr(parent, "enumvalues");
  1209. if (!enumvalues)
  1210. Setattr(parent, "enumvalues", Copy(symname));
  1211. else
  1212. Printv(enumvalues, ", ", symname, NIL);
  1213. Delete(scope);
  1214. }
  1215. Delete(newsymname);
  1216. Delete(tmpValue);
  1217. Swig_restore(n);
  1218. return SWIG_OK;
  1219. }
  1220. /* -----------------------------------------------------------------------
  1221. * constantWrapper()
  1222. * Used for wrapping constants - #define or %constant.
  1223. * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
  1224. * C# static const variables are generated for these.
  1225. * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
  1226. * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
  1227. * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
  1228. * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
  1229. * ------------------------------------------------------------------------ */
  1230. virtual int constantWrapper(Node *n) {
  1231. String *symname = Getattr(n, "sym:name");
  1232. SwigType *t = Getattr(n, "type");
  1233. SwigType *valuetype = Getattr(n, "valuetype");
  1234. ParmList *l = Getattr(n, "parms");
  1235. String *tm;
  1236. String *return_type = NewString("");
  1237. String *constants_code = NewString("");
  1238. Swig_save("constantWrapper", n, "value", NIL);
  1239. Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:cstype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:cstype:outattributes", NIL);
  1240. bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
  1241. const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
  1242. if (!is_enum_item) {
  1243. String *scope = 0;
  1244. if (proxy_class_name) {
  1245. String *nspace = getNSpace();
  1246. scope = NewString("");
  1247. if (nspace)
  1248. Printf(scope, "%s.", nspace);
  1249. Printf(scope, "%s", proxy_class_name);
  1250. } else {
  1251. scope = Copy(module_class_name);
  1252. }
  1253. if (!addSymbol(itemname, n, scope))
  1254. return SWIG_ERROR;
  1255. Delete(scope);
  1256. }
  1257. // The %csconst feature determines how the constant value is obtained
  1258. int const_feature_flag = GetFlag(n, "feature:cs:const");
  1259. /* Adjust the enum type for the Swig_typemap_lookup.
  1260. * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
  1261. if (is_enum_item) {
  1262. t = Getattr(parentNode(n), "enumtype");
  1263. Setattr(n, "type", t);
  1264. }
  1265. /* Attach the non-standard typemaps to the parameter list. */
  1266. Swig_typemap_attach_parms("cstype", l, NULL);
  1267. /* Get C# return types */
  1268. bool classname_substituted_flag = false;
  1269. if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
  1270. String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
  1271. if (cstypeout)
  1272. tm = cstypeout;
  1273. classname_substituted_flag = substituteClassname(t, tm);
  1274. Printf(return_type, "%s", tm);
  1275. } else {
  1276. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
  1277. }
  1278. // Default (octal) escaping is no good - change to hex escaped value
  1279. String *hexescaped_value = Getattr(n, "rawvalue") ? NewStringf("%(hexescape)s", Getattr(n, "rawvalue")) : 0;
  1280. // Add the stripped quotes back in
  1281. String *new_value = NewString("");
  1282. if (SwigType_type(t) == T_STRING) {
  1283. Printf(new_value, "\"%s\"", hexescaped_value ? hexescaped_value : Copy(Getattr(n, "value")));
  1284. Setattr(n, "value", new_value);
  1285. } else if (SwigType_type(t) == T_CHAR) {
  1286. Printf(new_value, "\'%s\'", hexescaped_value ? hexescaped_value : Copy(Getattr(n, "value")));
  1287. Setattr(n, "value", new_value);
  1288. }
  1289. const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
  1290. if (outattributes)
  1291. Printf(constants_code, " %s\n", outattributes);
  1292. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  1293. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  1294. Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
  1295. // Check for the %csconstvalue feature
  1296. String *value = Getattr(n, "feature:cs:constvalue");
  1297. if (value) {
  1298. Printf(constants_code, "%s;\n", value);
  1299. } else if (!const_feature_flag) {
  1300. // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
  1301. if (classname_substituted_flag) {
  1302. if (SwigType_isenum(t)) {
  1303. // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
  1304. Printf(constants_code, "(%s)%s.%s();\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1305. } else {
  1306. // This handles function pointers using the %constant directive
  1307. Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1308. }
  1309. } else {
  1310. Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1311. }
  1312. // Each constant and enum value is wrapped with a separate PInvoke function call
  1313. SetFlag(n, "feature:immutable");
  1314. enum_constant_flag = true;
  1315. variableWrapper(n);
  1316. enum_constant_flag = false;
  1317. } else {
  1318. // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
  1319. if (Getattr(n, "wrappedasconstant")) {
  1320. if (SwigType_type(t) == T_CHAR) {
  1321. if (SwigType_type(valuetype) == T_CHAR)
  1322. Printf(constants_code, "\'%(hexescape)s\';\n", Getattr(n, "staticmembervariableHandler:value"));
  1323. else
  1324. Printf(constants_code, "(char)%s;\n", Getattr(n, "staticmembervariableHandler:value"));
  1325. } else {
  1326. Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
  1327. }
  1328. } else {
  1329. Printf(constants_code, "%s;\n", Getattr(n, "value"));
  1330. }
  1331. }
  1332. // Emit the generated code to appropriate place
  1333. // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
  1334. if (!is_enum_item) {
  1335. if (proxy_flag && wrapping_member_flag)
  1336. Printv(proxy_class_constants_code, constants_code, NIL);
  1337. else
  1338. Printv(module_class_constants_code, constants_code, NIL);
  1339. }
  1340. // Cleanup
  1341. Swig_restore(n);
  1342. Delete(new_value);
  1343. Delete(return_type);
  1344. Delete(constants_code);
  1345. return SWIG_OK;
  1346. }
  1347. /* -----------------------------------------------------------------------------
  1348. * insertDirective()
  1349. * ----------------------------------------------------------------------------- */
  1350. virtual int insertDirective(Node *n) {
  1351. int ret = SWIG_OK;
  1352. String *code = Getattr(n, "code");
  1353. String *section = Getattr(n, "section");
  1354. Replaceall(code, "$module", module_class_name);
  1355. Replaceall(code, "$imclassname", imclass_name);
  1356. Replaceall(code, "$dllimport", dllimport);
  1357. if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
  1358. if (proxy_class_code) {
  1359. Swig_typemap_replace_embedded_typemap(code, n);
  1360. int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
  1361. Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
  1362. }
  1363. } else {
  1364. ret = Language::insertDirective(n);
  1365. }
  1366. return ret;
  1367. }
  1368. /* -----------------------------------------------------------------------------
  1369. * pragmaDirective()
  1370. *
  1371. * Valid Pragmas:
  1372. * imclassbase - base (extends) for the intermediary class
  1373. * imclassclassmodifiers - class modifiers for the intermediary class
  1374. * imclasscode - text (C# code) is copied verbatim to the intermediary class
  1375. * imclassimports - import statements for the intermediary class
  1376. * imclassinterfaces - interface (implements) for the intermediary class
  1377. *
  1378. * modulebase - base (extends) for the module class
  1379. * moduleclassmodifiers - class modifiers for the module class
  1380. * modulecode - text (C# code) is copied verbatim to the module class
  1381. * moduleimports - import statements for the module class
  1382. * moduleinterfaces - interface (implements) for the module class
  1383. *
  1384. * ----------------------------------------------------------------------------- */
  1385. virtual int pragmaDirective(Node *n) {
  1386. if (!ImportMode) {
  1387. String *lang = Getattr(n, "lang");
  1388. String *code = Getattr(n, "name");
  1389. String *value = Getattr(n, "value");
  1390. if (Strcmp(lang, "csharp") == 0) {
  1391. String *strvalue = NewString(value);
  1392. Replaceall(strvalue, "\\\"", "\"");
  1393. if (Strcmp(code, "imclassbase") == 0) {
  1394. Delete(imclass_baseclass);
  1395. imclass_baseclass = Copy(strvalue);
  1396. } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
  1397. Delete(imclass_class_modifiers);
  1398. imclass_class_modifiers = Copy(strvalue);
  1399. } else if (Strcmp(code, "imclasscode") == 0) {
  1400. Printf(imclass_class_code, "%s\n", strvalue);
  1401. } else if (Strcmp(code, "imclassimports") == 0) {
  1402. Delete(imclass_imports);
  1403. imclass_imports = Copy(strvalue);
  1404. } else if (Strcmp(code, "imclassinterfaces") == 0) {
  1405. Delete(imclass_interfaces);
  1406. imclass_interfaces = Copy(strvalue);
  1407. } else if (Strcmp(code, "modulebase") == 0) {
  1408. Delete(module_baseclass);
  1409. module_baseclass = Copy(strvalue);
  1410. } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
  1411. Delete(module_class_modifiers);
  1412. module_class_modifiers = Copy(strvalue);
  1413. } else if (Strcmp(code, "modulecode") == 0) {
  1414. Printf(module_class_code, "%s\n", strvalue);
  1415. } else if (Strcmp(code, "moduleimports") == 0) {
  1416. Delete(module_imports);
  1417. module_imports = Copy(strvalue);
  1418. } else if (Strcmp(code, "moduleinterfaces") == 0) {
  1419. Delete(module_interfaces);
  1420. module_interfaces = Copy(strvalue);
  1421. } else {
  1422. Swig_error(input_file, line_number, "Unrecognized pragma.\n");
  1423. }
  1424. Delete(strvalue);
  1425. }
  1426. }
  1427. return Language::pragmaDirective(n);
  1428. }
  1429. /* -----------------------------------------------------------------------------
  1430. * getQualifiedInterfaceName()
  1431. * ----------------------------------------------------------------------------- */
  1432. String *getQualifiedInterfaceName(Node *n) {
  1433. String *ret = Getattr(n, "interface:qname");
  1434. if (!ret) {
  1435. String *nspace = Getattr(n, "sym:nspace");
  1436. String *interface_name = Getattr(n, "interface:name");
  1437. if (nspace) {
  1438. if (namespce)
  1439. ret = NewStringf("%s.%s.%s", namespce, nspace, interface_name);
  1440. else
  1441. ret = NewStringf("%s.%s", nspace, interface_name);
  1442. } else {
  1443. ret = Copy(interface_name);
  1444. }
  1445. Setattr(n, "interface:qname", ret);
  1446. }
  1447. return ret;
  1448. }
  1449. /* -----------------------------------------------------------------------------
  1450. * getInterfaceName()
  1451. * ----------------------------------------------------------------------------- */
  1452. String *getInterfaceName(SwigType *t, bool qualified) {
  1453. String *interface_name = NULL;
  1454. if (proxy_flag) {
  1455. Node *n = classLookup(t);
  1456. if (n && Getattr(n, "interface:name"))
  1457. interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
  1458. }
  1459. return interface_name;
  1460. }
  1461. /* -----------------------------------------------------------------------------
  1462. * addInterfaceNameAndUpcasts()
  1463. * ----------------------------------------------------------------------------- */
  1464. void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, List *base_list, SwigType *c_classname) {
  1465. for (Iterator it = First(base_list); it.item; it = Next(it)) {
  1466. Node *base = it.item;
  1467. SwigType *c_baseclassname = Getattr(base, "name");
  1468. String *interface_name = Getattr(base, "interface:name");
  1469. if (Len(interface_list))
  1470. Append(interface_list, ", ");
  1471. Append(interface_list, interface_name);
  1472. Node *attributes = NewHash();
  1473. String *interface_code = Copy(typemapLookup(base, "csinterfacecode", Getattr(base, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes));
  1474. String *cptr_method_name = 0;
  1475. if (interface_code) {
  1476. Replaceall(interface_code, "$interfacename", interface_name);
  1477. Printv(interface_upcasts, interface_code, NIL);
  1478. cptr_method_name = Copy(Getattr(attributes, "tmap:csinterfacecode:cptrmethod"));
  1479. }
  1480. if (!cptr_method_name)
  1481. cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
  1482. Replaceall(cptr_method_name, ".", "_");
  1483. Replaceall(cptr_method_name, "$interfacename", interface_name);
  1484. String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
  1485. upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
  1486. Delete(upcast_method_name);
  1487. Delete(cptr_method_name);
  1488. Delete(interface_code);
  1489. }
  1490. }
  1491. /* -----------------------------------------------------------------------------
  1492. * upcastsCode()
  1493. *
  1494. * Add code for C++ casting to base class
  1495. * ----------------------------------------------------------------------------- */
  1496. void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
  1497. String *wname = Swig_name_wrapper(upcast_method_name);
  1498. Printv(imclass_cppcasts_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
  1499. Printf(imclass_cppcasts_code, " public static extern global::System.IntPtr %s(global::System.IntPtr jarg1);\n", upcast_method_name);
  1500. Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
  1501. String *classname = SwigType_namestr(c_classname);
  1502. String *baseclassname = SwigType_namestr(c_baseclassname);
  1503. if (smart) {
  1504. String *smartnamestr = SwigType_namestr(smart);
  1505. String *bsmartnamestr = SwigType_namestr(smart);
  1506. // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
  1507. SwigType *rclassname = SwigType_typedef_resolve_all(classname);
  1508. SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname);
  1509. Replaceall(bsmartnamestr, rclassname, rbaseclassname);
  1510. Printv(upcasts_code,
  1511. "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n",
  1512. " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n"
  1513. "}\n", "\n", NIL);
  1514. Delete(rbaseclassname);
  1515. Delete(rclassname);
  1516. Delete(bsmartnamestr);
  1517. Delete(smartnamestr);
  1518. } else {
  1519. Printv(upcasts_code,
  1520. "SWIGEXPORT ", baseclassname, " * SWIGSTDCALL ", wname, "(", classname, " *jarg1) {\n",
  1521. " return (", baseclassname, " *)jarg1;\n"
  1522. "}\n", "\n", NIL);
  1523. }
  1524. Delete(baseclassname);
  1525. Delete(classname);
  1526. Delete(wname);
  1527. }
  1528. /* -----------------------------------------------------------------------------
  1529. * emitProxyClassDefAndCPPCasts()
  1530. * ----------------------------------------------------------------------------- */
  1531. void emitProxyClassDefAndCPPCasts(Node *n) {
  1532. SwigType *c_classname = Getattr(n, "name");
  1533. SwigType *c_baseclassname = NULL;
  1534. String *baseclass = NULL;
  1535. String *interface_list = NewStringEmpty();
  1536. String *interface_upcasts = NewStringEmpty();
  1537. SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
  1538. bool feature_director = Swig_directorclass(n) ? true : false;
  1539. bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
  1540. SwigType *smart = Swig_cparse_smartptr(n);
  1541. // Inheritance from pure C# classes
  1542. Node *attributes = NewHash();
  1543. const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
  1544. bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
  1545. bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
  1546. Delete(attributes);
  1547. // C++ inheritance
  1548. if (!purebase_replace) {
  1549. List *baselist = Getattr(n, "bases");
  1550. if (baselist) {
  1551. Iterator base = First(baselist);
  1552. while (base.item) {
  1553. if (!(GetFlag(base.item, "feature:ignore") || GetFlag(base.item, "feature:interface"))) {
  1554. SwigType *baseclassname = Getattr(base.item, "name");
  1555. if (!c_baseclassname) {
  1556. String *name = getProxyName(baseclassname);
  1557. if (name) {
  1558. c_baseclassname = baseclassname;
  1559. baseclass = name;
  1560. }
  1561. } else {
  1562. /* Warn about multiple inheritance for additional base class(es) */
  1563. String *proxyclassname = Getattr(n, "classtypeobj");
  1564. Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
  1565. "Warning for %s, base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
  1566. }
  1567. }
  1568. base = Next(base);
  1569. }
  1570. }
  1571. }
  1572. List *interface_bases = Getattr(n, "interface:bases");
  1573. if (interface_bases)
  1574. addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
  1575. bool derived = baseclass != 0;
  1576. if (derived && purebase_notderived)
  1577. pure_baseclass = empty_string;
  1578. const String *wanted_base = baseclass ? baseclass : pure_baseclass;
  1579. if (purebase_replace) {
  1580. wanted_base = pure_baseclass;
  1581. derived = false;
  1582. baseclass = NULL;
  1583. if (purebase_notderived)
  1584. Swig_error(Getfile(n), Getline(n), "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
  1585. } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
  1586. Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
  1587. "Warning for %s, base %s ignored. Multiple inheritance is not supported in C#. "
  1588. "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
  1589. }
  1590. // Pure C# interfaces
  1591. const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
  1592. if (*Char(interface_list) && *Char(pure_interfaces))
  1593. Append(interface_list, ", ");
  1594. Append(interface_list, pure_interfaces);
  1595. // Start writing the proxy class
  1596. if (!has_outerclass)
  1597. Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
  1598. "\n", NIL);
  1599. // Class attributes
  1600. const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
  1601. if (csattributes && *Char(csattributes))
  1602. Printf(proxy_class_def, "%s\n", csattributes);
  1603. Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
  1604. " $csclassname", // Class name and base class
  1605. (*Char(wanted_base) || *Char(interface_list)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(interface_list)) ? // Interfaces
  1606. ", " : "", interface_list, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
  1607. typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
  1608. NIL);
  1609. // C++ destructor is wrapped by the Finalize and Dispose methods
  1610. const char *tmap_method = derived ? "csdestruct_derived" : "csdestruct";
  1611. const String *tm = typemapExists(n, tmap_method, typemap_lookup_type);
  1612. if (tm) {
  1613. Swig_error(Getfile(tm), Getline(tm),
  1614. "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
  1615. tmap_method, proxy_class_name);
  1616. }
  1617. tmap_method = "csfinalize";
  1618. tm = typemapExists(n, tmap_method, typemap_lookup_type);
  1619. if (tm) {
  1620. Swig_error(Getfile(tm), Getline(tm),
  1621. "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
  1622. tmap_method, proxy_class_name);
  1623. }
  1624. tmap_method = derived ? "csdisposing_derived" : "csdisposing";
  1625. String *destruct = NewString("");
  1626. attributes = NewHash();
  1627. const String *destruct_methodname = NULL;
  1628. const String *destruct_methodmodifiers = NULL;
  1629. const String *destruct_parameters = NULL;
  1630. if (derived) {
  1631. tm = typemapLookup(n, "csdisposing_derived", typemap_lookup_type, WARN_NONE, attributes);
  1632. destruct_methodname = Getattr(attributes, "tmap:csdisposing_derived:methodname");
  1633. destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing_derived:methodmodifiers");
  1634. destruct_parameters = Getattr(attributes, "tmap:csdisposing_derived:parameters");
  1635. } else {
  1636. tm = typemapLookup(n, "csdisposing", typemap_lookup_type, WARN_NONE, attributes);
  1637. destruct_methodname = Getattr(attributes, "tmap:csdisposing:methodname");
  1638. destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing:methodmodifiers");
  1639. destruct_parameters = Getattr(attributes, "tmap:csdisposing:parameters");
  1640. }
  1641. if (tm && *Char(tm)) {
  1642. if (!destruct_methodname) {
  1643. Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in %s typemap for %s\n", tmap_method, proxy_class_name);
  1644. }
  1645. if (!destruct_methodmodifiers) {
  1646. Swig_error(Getfile(n), Getline(n),
  1647. "No methodmodifiers attribute defined in %s typemap for %s.\n", tmap_method, proxy_class_name);
  1648. }
  1649. if (!destruct_parameters)
  1650. destruct_parameters = empty_string;
  1651. }
  1652. // Emit the Finalize and Dispose methods
  1653. if (tm) {
  1654. // Finalize and Dispose methods
  1655. Printv(proxy_class_def, typemapLookup(n, derived ? "csdispose_derived" : "csdispose", typemap_lookup_type, WARN_NONE), NIL);
  1656. // Dispose(bool disposing) method
  1657. Printv(destruct, tm, NIL);
  1658. if (*Char(destructor_call))
  1659. Replaceall(destruct, "$imcall", destructor_call);
  1660. else
  1661. Replaceall(destruct, "$imcall", "throw new global::System.MethodAccessException(\"C++ destructor does not have public access\")");
  1662. if (*Char(destruct)) {
  1663. Printv(proxy_class_def, "\n ", NIL);
  1664. const String *methodmods = Getattr(n, "destructmethodmodifiers");
  1665. if (methodmods)
  1666. Printv(proxy_class_def, methodmods, NIL);
  1667. else
  1668. Printv(proxy_class_def, destruct_methodmodifiers, " ", derived ? "override" : "virtual", NIL);
  1669. Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ") ", destruct, "\n", NIL);
  1670. }
  1671. }
  1672. if (*Char(interface_upcasts))
  1673. Printv(proxy_class_def, interface_upcasts, NIL);
  1674. if (feature_director) {
  1675. // Generate director connect method
  1676. // put this in classDirectorEnd ???
  1677. Printf(proxy_class_code, " private void SwigDirectorConnect() {\n");
  1678. int i;
  1679. for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  1680. UpcallData *udata = Getitem(dmethods_seq, i);
  1681. String *method = Getattr(udata, "method");
  1682. String *methid = Getattr(udata, "class_methodidx");
  1683. String *overname = Getattr(udata, "overname");
  1684. Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
  1685. Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirectorMethod%s);\n", methid, proxy_class_name, methid, overname);
  1686. }
  1687. String *director_connect_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
  1688. Printf(proxy_class_code, " %s.%s(swigCPtr", imclass_name, director_connect_method_name);
  1689. for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  1690. UpcallData *udata = Getitem(dmethods_seq, i);
  1691. String *methid = Getattr(udata, "class_methodidx");
  1692. Printf(proxy_class_code, ", swigDelegate%s", methid);
  1693. }
  1694. Printf(proxy_class_code, ");\n");
  1695. Printf(proxy_class_code, " }\n");
  1696. if (first_class_dmethod < curr_class_dmethod) {
  1697. // Only emit if there is at least one director method
  1698. Printf(proxy_class_code, "\n");
  1699. Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) {\n");
  1700. Printf(proxy_class_code, " global::System.Reflection.MethodInfo[] methodInfos = this.GetType().GetMethods(\n");
  1701. Printf(proxy_class_code, " global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance);\n");
  1702. Printf(proxy_class_code, " foreach (global::System.Reflection.MethodInfo methodInfo in methodInfos) {\n");
  1703. Printf(proxy_class_code, " if (methodInfo.DeclaringType == null)\n");
  1704. Printf(proxy_class_code, " continue;\n\n");
  1705. Printf(proxy_class_code, " if (methodInfo.Name != methodName)\n");
  1706. Printf(proxy_class_code, " continue;\n\n");
  1707. Printf(proxy_class_code, " var parameters = methodInfo.GetParameters();\n");
  1708. Printf(proxy_class_code, " if (parameters.Length != methodTypes.Length)\n");
  1709. Printf(proxy_class_code, " continue;\n\n");
  1710. Printf(proxy_class_code, " bool parametersMatch = true;\n");
  1711. Printf(proxy_class_code, " for (var i = 0; i < parameters.Length; i++) {\n");
  1712. Printf(proxy_class_code, " if (parameters[i].ParameterType != methodTypes[i]) {\n");
  1713. Printf(proxy_class_code, " parametersMatch = false;\n");
  1714. Printf(proxy_class_code, " break;\n");
  1715. Printf(proxy_class_code, " }\n");
  1716. Printf(proxy_class_code, " }\n\n");
  1717. Printf(proxy_class_code, " if (!parametersMatch)\n");
  1718. Printf(proxy_class_code, " continue;\n\n");
  1719. Printf(proxy_class_code, " if (methodInfo.IsVirtual && (methodInfo.DeclaringType.IsSubclassOf(typeof(%s))) &&\n", proxy_class_name);
  1720. Printf(proxy_class_code, " methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType) {\n");
  1721. Printf(proxy_class_code, " return true;\n");
  1722. Printf(proxy_class_code, " }\n");
  1723. Printf(proxy_class_code, " }\n\n");
  1724. Printf(proxy_class_code, " return false;\n");
  1725. /* Could add this code to cover corner case where the GetMethod() returns a method which allows type
  1726. * promotion, eg it will return foo(double), if looking for foo(int).
  1727. if (hasDerivedMethod) {
  1728. hasDerivedMethod = false;
  1729. if (methodInfo != null)
  1730. {
  1731. hasDerivedMethod = true;
  1732. ParameterInfo[] parameterArray1 = methodInfo.GetParameters();
  1733. for (int i=0; i<methodTypes.Length; i++)
  1734. {
  1735. if (parameterArray1[0].ParameterType != methodTypes[0])
  1736. {
  1737. hasDerivedMethod = false;
  1738. break;
  1739. }
  1740. }
  1741. }
  1742. }
  1743. */
  1744. //Printf(proxy_class_code, " return hasDerivedMethod;\n");
  1745. Printf(proxy_class_code, " }\n");
  1746. }
  1747. if (Len(director_delegate_callback) > 0)
  1748. Printv(proxy_class_code, director_delegate_callback, NIL);
  1749. if (Len(director_delegate_definitions) > 0)
  1750. Printv(proxy_class_code, "\n", director_delegate_definitions, NIL);
  1751. if (Len(director_delegate_instances) > 0)
  1752. Printv(proxy_class_code, "\n", director_delegate_instances, NIL);
  1753. if (Len(director_method_types) > 0)
  1754. Printv(proxy_class_code, "\n", director_method_types, NIL);
  1755. Delete(director_callback_typedefs);
  1756. director_callback_typedefs = NULL;
  1757. Delete(director_callbacks);
  1758. director_callbacks = NULL;
  1759. Delete(director_delegate_callback);
  1760. director_delegate_callback = NULL;
  1761. Delete(director_delegate_definitions);
  1762. director_delegate_definitions = NULL;
  1763. Delete(director_delegate_instances);
  1764. director_delegate_instances = NULL;
  1765. Delete(director_method_types);
  1766. director_method_types = NULL;
  1767. Delete(director_connect_parms);
  1768. director_connect_parms = NULL;
  1769. Delete(director_connect_method_name);
  1770. }
  1771. Delete(interface_upcasts);
  1772. Delete(interface_list);
  1773. Delete(attributes);
  1774. Delete(destruct);
  1775. // Emit extra user code
  1776. Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
  1777. "\n", NIL);
  1778. if (derived) {
  1779. String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
  1780. upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
  1781. Delete(upcast_method_name);
  1782. }
  1783. Delete(smart);
  1784. }
  1785. /* ----------------------------------------------------------------------
  1786. * emitInterfaceDeclaration()
  1787. * ---------------------------------------------------------------------- */
  1788. void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface) {
  1789. Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
  1790. Printv(f_interface, typemapLookup(n, "csinterfacemodifiers", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL);
  1791. Printf(f_interface, " %s", interface_name);
  1792. if (List *baselist = Getattr(n, "bases")) {
  1793. String *bases = 0;
  1794. for (Iterator base = First(baselist); base.item; base = Next(base)) {
  1795. if (GetFlag(base.item, "feature:ignore") || !GetFlag(base.item, "feature:interface"))
  1796. continue; // TODO: warn about skipped non-interface bases
  1797. String *base_iname = Getattr(base.item, "interface:name");
  1798. if (!bases)
  1799. bases = NewStringf(" : %s", base_iname);
  1800. else {
  1801. Append(bases, ", ");
  1802. Append(bases, base_iname);
  1803. }
  1804. }
  1805. if (bases) {
  1806. Printv(f_interface, bases, NIL);
  1807. Delete(bases);
  1808. }
  1809. }
  1810. Printf(f_interface, " {\n");
  1811. Node *attributes = NewHash();
  1812. String *interface_code = Copy(typemapLookup(n, "csinterfacecode", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes));
  1813. if (interface_code) {
  1814. String *interface_declaration = Copy(Getattr(attributes, "tmap:csinterfacecode:declaration"));
  1815. if (interface_declaration) {
  1816. Replaceall(interface_declaration, "$interfacename", interface_name);
  1817. Printv(f_interface, interface_declaration, NIL);
  1818. Delete(interface_declaration);
  1819. }
  1820. Delete(interface_code);
  1821. }
  1822. }
  1823. /* ----------------------------------------------------------------------
  1824. * classHandler()
  1825. * ---------------------------------------------------------------------- */
  1826. virtual int classHandler(Node *n) {
  1827. String *nspace = getNSpace();
  1828. File *f_proxy = NULL;
  1829. File *f_interface = NULL;
  1830. // save class local variables
  1831. String *old_proxy_class_name = proxy_class_name;
  1832. String *old_full_imclass_name = full_imclass_name;
  1833. String *old_destructor_call = destructor_call;
  1834. String *old_proxy_class_constants_code = proxy_class_constants_code;
  1835. String *old_proxy_class_def = proxy_class_def;
  1836. String *old_proxy_class_code = proxy_class_code;
  1837. bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
  1838. String *old_interface_class_code = interface_class_code;
  1839. interface_class_code = 0;
  1840. if (proxy_flag) {
  1841. proxy_class_name = NewString(Getattr(n, "sym:name"));
  1842. String *interface_name = GetFlag(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
  1843. if (Node *outer = Getattr(n, "nested:outer")) {
  1844. String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
  1845. for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
  1846. Push(outerClassesPrefix, ".");
  1847. Push(outerClassesPrefix, Getattr(outer, "sym:name"));
  1848. }
  1849. String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
  1850. if (!addSymbol(proxy_class_name, n, fnspace))
  1851. return SWIG_ERROR;
  1852. if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
  1853. return SWIG_ERROR;
  1854. if (nspace)
  1855. Delete(fnspace);
  1856. Delete(outerClassesPrefix);
  1857. } else {
  1858. if (!addSymbol(proxy_class_name, n, nspace))
  1859. return SWIG_ERROR;
  1860. if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
  1861. return SWIG_ERROR;
  1862. }
  1863. if (!nspace) {
  1864. full_imclass_name = NewStringf("%s", imclass_name);
  1865. if (Cmp(proxy_class_name, imclass_name) == 0) {
  1866. Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
  1867. Exit(EXIT_FAILURE);
  1868. }
  1869. if (Cmp(proxy_class_name, module_class_name) == 0) {
  1870. Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
  1871. Exit(EXIT_FAILURE);
  1872. }
  1873. } else {
  1874. if (namespce) {
  1875. full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
  1876. } else {
  1877. full_imclass_name = NewStringf("%s", imclass_name);
  1878. }
  1879. }
  1880. if (!has_outerclass) {
  1881. String *output_directory = outputDirectory(nspace);
  1882. f_proxy = getOutputFile(output_directory, proxy_class_name);
  1883. addOpenNamespace(nspace, f_proxy);
  1884. Delete(output_directory);
  1885. }
  1886. else
  1887. ++nesting_depth;
  1888. proxy_class_def = NewString("");
  1889. proxy_class_code = NewString("");
  1890. destructor_call = NewString("");
  1891. proxy_class_constants_code = NewString("");
  1892. if (GetFlag(n, "feature:interface")) {
  1893. interface_class_code = NewString("");
  1894. String *output_directory = outputDirectory(nspace);
  1895. f_interface = getOutputFile(output_directory, interface_name);
  1896. addOpenNamespace(nspace, f_interface);
  1897. emitInterfaceDeclaration(n, interface_name, interface_class_code);
  1898. Delete(output_directory);
  1899. }
  1900. }
  1901. Language::classHandler(n);
  1902. if (proxy_flag) {
  1903. emitProxyClassDefAndCPPCasts(n);
  1904. String *csclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
  1905. Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
  1906. Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
  1907. Replaceall(proxy_class_constants_code, "$csclassname", proxy_class_name);
  1908. Replaceall(interface_class_code, "$csclassname", proxy_class_name);
  1909. Replaceall(proxy_class_def, "$csclazzname", csclazzname);
  1910. Replaceall(proxy_class_code, "$csclazzname", csclazzname);
  1911. Replaceall(proxy_class_constants_code, "$csclazzname", csclazzname);
  1912. Replaceall(interface_class_code, "$csclazzname", csclazzname);
  1913. Replaceall(proxy_class_def, "$module", module_class_name);
  1914. Replaceall(proxy_class_code, "$module", module_class_name);
  1915. Replaceall(proxy_class_constants_code, "$module", module_class_name);
  1916. Replaceall(interface_class_code, "$module", module_class_name);
  1917. Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
  1918. Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
  1919. Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
  1920. Replaceall(interface_class_code, "$imclassname", full_imclass_name);
  1921. Replaceall(proxy_class_def, "$dllimport", dllimport);
  1922. Replaceall(proxy_class_code, "$dllimport", dllimport);
  1923. Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
  1924. Replaceall(interface_class_code, "$dllimport", dllimport);
  1925. if (!has_outerclass)
  1926. Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
  1927. else {
  1928. Swig_offset_string(proxy_class_def, nesting_depth);
  1929. Append(old_proxy_class_code, proxy_class_def);
  1930. Swig_offset_string(proxy_class_code, nesting_depth);
  1931. Append(old_proxy_class_code, proxy_class_code);
  1932. }
  1933. // Write out all the constants
  1934. if (Len(proxy_class_constants_code) != 0) {
  1935. if (!has_outerclass)
  1936. Printv(f_proxy, proxy_class_constants_code, NIL);
  1937. else {
  1938. Swig_offset_string(proxy_class_constants_code, nesting_depth);
  1939. Append(old_proxy_class_code, proxy_class_constants_code);
  1940. }
  1941. }
  1942. if (!has_outerclass) {
  1943. Printf(f_proxy, "}\n");
  1944. addCloseNamespace(nspace, f_proxy);
  1945. if (f_proxy != f_single_out)
  1946. Delete(f_proxy);
  1947. f_proxy = NULL;
  1948. } else {
  1949. for (int i = 0; i < nesting_depth; ++i)
  1950. Append(old_proxy_class_code, " ");
  1951. Append(old_proxy_class_code, "}\n\n");
  1952. --nesting_depth;
  1953. }
  1954. if (f_interface) {
  1955. Printv(f_interface, interface_class_code, "}\n", NIL);
  1956. addCloseNamespace(nspace, f_interface);
  1957. if (f_interface != f_single_out)
  1958. Delete(f_interface);
  1959. f_interface = 0;
  1960. }
  1961. emitDirectorExtraMethods(n);
  1962. Delete(interface_class_code);
  1963. interface_class_code = old_interface_class_code;
  1964. Delete(csclazzname);
  1965. Delete(proxy_class_name);
  1966. proxy_class_name = old_proxy_class_name;
  1967. Delete(full_imclass_name);
  1968. full_imclass_name = old_full_imclass_name;
  1969. Delete(destructor_call);
  1970. destructor_call = old_destructor_call;
  1971. Delete(proxy_class_constants_code);
  1972. proxy_class_constants_code = old_proxy_class_constants_code;
  1973. Delete(proxy_class_def);
  1974. proxy_class_def = old_proxy_class_def;
  1975. Delete(proxy_class_code);
  1976. proxy_class_code = old_proxy_class_code;
  1977. }
  1978. return SWIG_OK;
  1979. }
  1980. /* ----------------------------------------------------------------------
  1981. * memberfunctionHandler()
  1982. * ---------------------------------------------------------------------- */
  1983. virtual int memberfunctionHandler(Node *n) {
  1984. Language::memberfunctionHandler(n);
  1985. if (proxy_flag) {
  1986. String *overloaded_name = getOverloadedName(n);
  1987. String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
  1988. Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
  1989. Setattr(n, "imfuncname", intermediary_function_name);
  1990. proxyClassFunctionHandler(n);
  1991. Delete(overloaded_name);
  1992. }
  1993. return SWIG_OK;
  1994. }
  1995. /* ----------------------------------------------------------------------
  1996. * staticmemberfunctionHandler()
  1997. * ---------------------------------------------------------------------- */
  1998. virtual int staticmemberfunctionHandler(Node *n) {
  1999. static_flag = true;
  2000. Language::staticmemberfunctionHandler(n);
  2001. if (proxy_flag) {
  2002. String *overloaded_name = getOverloadedName(n);
  2003. String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
  2004. Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
  2005. Setattr(n, "imfuncname", intermediary_function_name);
  2006. proxyClassFunctionHandler(n);
  2007. Delete(overloaded_name);
  2008. }
  2009. static_flag = false;
  2010. return SWIG_OK;
  2011. }
  2012. /* -----------------------------------------------------------------------------
  2013. * proxyClassFunctionHandler()
  2014. *
  2015. * Function called for creating a C# wrapper function around a c++ function in the
  2016. * proxy class. Used for both static and non-static C++ class functions.
  2017. * C++ class static functions map to C# static functions.
  2018. * Two extra attributes in the Node must be available. These are "proxyfuncname" -
  2019. * the name of the C# class proxy function, which in turn will call "imfuncname" -
  2020. * the intermediary (PInvoke) function name in the intermediary class.
  2021. * ----------------------------------------------------------------------------- */
  2022. void proxyClassFunctionHandler(Node *n) {
  2023. SwigType *t = Getattr(n, "type");
  2024. ParmList *l = Getattr(n, "parms");
  2025. String *intermediary_function_name = Getattr(n, "imfuncname");
  2026. String *proxy_function_name = Getattr(n, "proxyfuncname");
  2027. String *tm;
  2028. Parm *p;
  2029. Parm *last_parm = 0;
  2030. int i;
  2031. String *imcall = NewString("");
  2032. String *return_type = NewString("");
  2033. String *function_code = NewString("");
  2034. bool setter_flag = false;
  2035. String *pre_code = NewString("");
  2036. String *post_code = NewString("");
  2037. String *terminator_code = NewString("");
  2038. bool is_interface = GetFlag(parentNode(n), "feature:interface") && !checkAttribute(n, "kind", "variable")
  2039. && !static_flag && Getattr(n, "interface:owner") == 0;
  2040. if (!proxy_flag)
  2041. return;
  2042. // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
  2043. if (Getattr(n, "overload:ignore"))
  2044. return;
  2045. // Don't generate proxy method for additional explicitcall method used in directors
  2046. if (GetFlag(n, "explicitcall"))
  2047. return;
  2048. if (l) {
  2049. if (SwigType_type(Getattr(l, "type")) == T_VOID) {
  2050. l = nextSibling(l);
  2051. }
  2052. }
  2053. /* Attach the non-standard typemaps to the parameter list */
  2054. Swig_typemap_attach_parms("in", l, NULL);
  2055. Swig_typemap_attach_parms("cstype", l, NULL);
  2056. Swig_typemap_attach_parms("csin", l, NULL);
  2057. /* Get return types */
  2058. if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
  2059. // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
  2060. SwigType *covariant = Getattr(n, "covariant");
  2061. String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
  2062. if (cstypeout)
  2063. tm = cstypeout;
  2064. substituteClassname(covariant ? covariant : t, tm);
  2065. Printf(return_type, "%s", tm);
  2066. if (covariant)
  2067. Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number,
  2068. "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(covariant, 0));
  2069. } else {
  2070. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
  2071. }
  2072. if (wrapping_member_flag && !enum_constant_flag) {
  2073. // Properties
  2074. setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
  2075. if (setter_flag)
  2076. Swig_typemap_attach_parms("csvarin", l, NULL);
  2077. }
  2078. /* Start generating the proxy function */
  2079. const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
  2080. if (outattributes)
  2081. Printf(function_code, " %s\n", outattributes);
  2082. const String *csattributes = Getattr(n, "feature:cs:attributes");
  2083. if (csattributes)
  2084. Printf(function_code, " %s\n", csattributes);
  2085. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  2086. if (methodmods) {
  2087. if (is_smart_pointer()) {
  2088. // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
  2089. String *mmods = Copy(methodmods);
  2090. Replaceall(mmods, "override", "");
  2091. Replaceall(mmods, "virtual", "");
  2092. Replaceall(mmods, "new", "");
  2093. Chop(mmods); // remove trailing whitespace
  2094. Printf(function_code, " %s ", mmods);
  2095. Delete(mmods);
  2096. } else {
  2097. Printf(function_code, " %s ", methodmods);
  2098. }
  2099. } else {
  2100. methodmods = (is_public(n) ? public_string : protected_string);
  2101. Printf(function_code, " %s ", methodmods);
  2102. if (!is_smart_pointer()) {
  2103. // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
  2104. if (Getattr(n, "override"))
  2105. Printf(function_code, "override ");
  2106. else if (checkAttribute(n, "storage", "virtual"))
  2107. Printf(function_code, "virtual ");
  2108. if (Getattr(n, "hides"))
  2109. Printf(function_code, "new ");
  2110. }
  2111. }
  2112. if (static_flag)
  2113. Printf(function_code, "static ");
  2114. Printf(function_code, "%s %s(", return_type, proxy_function_name);
  2115. if (is_interface)
  2116. Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
  2117. Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
  2118. if (!static_flag)
  2119. Printf(imcall, "swigCPtr");
  2120. emit_mark_varargs(l);
  2121. int gencomma = !static_flag;
  2122. /* Output each parameter */
  2123. for (i = 0, p = l; p; i++) {
  2124. /* Ignored varargs */
  2125. if (checkAttribute(p, "varargs:ignore", "1")) {
  2126. p = nextSibling(p);
  2127. continue;
  2128. }
  2129. /* Ignored parameters */
  2130. if (checkAttribute(p, "tmap:in:numinputs", "0")) {
  2131. p = Getattr(p, "tmap:in:next");
  2132. continue;
  2133. }
  2134. /* Ignore the 'this' argument for variable wrappers */
  2135. if (!(variable_wrapper_flag && i == 0)) {
  2136. SwigType *pt = Getattr(p, "type");
  2137. String *param_type = NewString("");
  2138. if (setter_flag)
  2139. last_parm = p;
  2140. /* Get the C# parameter type */
  2141. if ((tm = Getattr(p, "tmap:cstype"))) {
  2142. substituteClassname(pt, tm);
  2143. const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
  2144. Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  2145. } else {
  2146. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
  2147. }
  2148. if (gencomma)
  2149. Printf(imcall, ", ");
  2150. String *arg = makeParameterName(n, p, i, setter_flag);
  2151. // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
  2152. if ((tm = Getattr(p, "tmap:csin"))) {
  2153. substituteClassname(pt, tm);
  2154. Replaceall(tm, "$csinput", arg);
  2155. String *pre = Getattr(p, "tmap:csin:pre");
  2156. if (pre) {
  2157. substituteClassname(pt, pre);
  2158. Replaceall(pre, "$csinput", arg);
  2159. if (Len(pre_code) > 0)
  2160. Printf(pre_code, "\n");
  2161. Printv(pre_code, pre, NIL);
  2162. }
  2163. String *post = Getattr(p, "tmap:csin:post");
  2164. if (post) {
  2165. substituteClassname(pt, post);
  2166. Replaceall(post, "$csinput", arg);
  2167. if (Len(post_code) > 0)
  2168. Printf(post_code, "\n");
  2169. Printv(post_code, post, NIL);
  2170. }
  2171. String *terminator = Getattr(p, "tmap:csin:terminator");
  2172. if (terminator) {
  2173. substituteClassname(pt, terminator);
  2174. Replaceall(terminator, "$csinput", arg);
  2175. if (Len(terminator_code) > 0)
  2176. Insert(terminator_code, 0, "\n");
  2177. Insert(terminator_code, 0, terminator);
  2178. }
  2179. Printv(imcall, tm, NIL);
  2180. } else {
  2181. Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
  2182. }
  2183. /* Add parameter to proxy function */
  2184. if (gencomma >= 2) {
  2185. Printf(function_code, ", ");
  2186. if (is_interface)
  2187. Printf(interface_class_code, ", ");
  2188. }
  2189. gencomma = 2;
  2190. Printf(function_code, "%s %s", param_type, arg);
  2191. if (is_interface)
  2192. Printf(interface_class_code, "%s %s", param_type, arg);
  2193. Delete(arg);
  2194. Delete(param_type);
  2195. }
  2196. p = Getattr(p, "tmap:in:next");
  2197. }
  2198. Printf(imcall, ")");
  2199. Printf(function_code, ")");
  2200. if (is_interface)
  2201. Printf(interface_class_code, ");\n");
  2202. // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
  2203. if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
  2204. excodeSubstitute(n, tm, "csout", n);
  2205. bool is_pre_code = Len(pre_code) > 0;
  2206. bool is_post_code = Len(post_code) > 0;
  2207. bool is_terminator_code = Len(terminator_code) > 0;
  2208. if (is_pre_code || is_post_code || is_terminator_code) {
  2209. Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
  2210. if (is_post_code) {
  2211. Insert(tm, 0, "\n try ");
  2212. Printv(tm, " finally {\n", post_code, "\n }", NIL);
  2213. } else {
  2214. Insert(tm, 0, "\n ");
  2215. }
  2216. if (is_pre_code) {
  2217. Insert(tm, 0, pre_code);
  2218. Insert(tm, 0, "\n");
  2219. }
  2220. if (is_terminator_code) {
  2221. Printv(tm, "\n", terminator_code, NIL);
  2222. }
  2223. Insert(tm, 0, "{");
  2224. Printf(tm, "\n }");
  2225. }
  2226. if (GetFlag(n, "feature:new"))
  2227. Replaceall(tm, "$owner", "true");
  2228. else
  2229. Replaceall(tm, "$owner", "false");
  2230. substituteClassname(t, tm);
  2231. // For director methods: generate code to selectively make a normal polymorphic call or
  2232. // an explicit method call - needed to prevent infinite recursion calls in director methods.
  2233. Node *explicit_n = Getattr(n, "explicitcallnode");
  2234. if (explicit_n) {
  2235. String *ex_overloaded_name = getOverloadedName(explicit_n);
  2236. String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
  2237. String *ex_imcall = Copy(imcall);
  2238. Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
  2239. Replaceall(imcall, "$imfuncname", intermediary_function_name);
  2240. String *excode = NewString("");
  2241. Node *directorNode = Getattr(n, "directorNode");
  2242. UpcallData *udata = directorNode ? Getattr(directorNode, "upcalldata") : 0;
  2243. if (udata) {
  2244. String *methid = Getattr(udata, "class_methodidx");
  2245. if (!Cmp(return_type, "void"))
  2246. Printf(excode, "if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s)) %s; else %s", proxy_function_name, methid, ex_imcall, imcall);
  2247. else
  2248. Printf(excode, "(SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s) ? %s : %s)", proxy_function_name, methid, ex_imcall, imcall);
  2249. Clear(imcall);
  2250. Printv(imcall, excode, NIL);
  2251. } else {
  2252. // probably an ignored method or nodirector
  2253. }
  2254. Delete(excode);
  2255. Delete(ex_overloaded_name);
  2256. } else {
  2257. Replaceall(imcall, "$imfuncname", intermediary_function_name);
  2258. }
  2259. Replaceall(tm, "$imfuncname", intermediary_function_name);
  2260. Replaceall(tm, "$imcall", imcall);
  2261. } else {
  2262. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
  2263. }
  2264. if (wrapping_member_flag && !enum_constant_flag) {
  2265. // Properties
  2266. if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
  2267. // Get the C# variable type - obtained differently depending on whether a setter is required.
  2268. String *variable_type = return_type;
  2269. if (setter_flag) {
  2270. assert(last_parm); // (last parameter is the only parameter for properties)
  2271. /* Get variable type - ensure the variable name is fully resolved during typemap lookup via the symbol table set in NewParmNode */
  2272. SwigType *cvariable_type = Getattr(last_parm, "type");
  2273. Parm *variable_parm = NewParmNode(cvariable_type, n);
  2274. if ((tm = Swig_typemap_lookup("cstype", variable_parm, "", 0))) {
  2275. String *cstypeout = Getattr(variable_parm, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
  2276. if (cstypeout)
  2277. tm = cstypeout;
  2278. substituteClassname(cvariable_type, tm);
  2279. variable_type = tm;
  2280. } else {
  2281. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(cvariable_type, 0));
  2282. }
  2283. }
  2284. const String *csattributes = Getattr(n, "feature:cs:attributes");
  2285. if (csattributes)
  2286. Printf(proxy_class_code, " %s\n", csattributes);
  2287. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  2288. if (!methodmods)
  2289. methodmods = (is_public(n) ? public_string : protected_string);
  2290. Printf(proxy_class_code, " %s %s%s %s {", methodmods, static_flag ? "static " : "", variable_type, variable_name);
  2291. }
  2292. generate_property_declaration_flag = false;
  2293. if (setter_flag) {
  2294. // Setter method
  2295. assert(last_parm); // (last parameter is the only parameter for properties)
  2296. SwigType *cvariable_type = Getattr(last_parm, "type");
  2297. Parm *variable_parm = NewParmNode(cvariable_type, n);
  2298. if ((tm = Swig_typemap_lookup("csvarin", variable_parm, "", 0))) {
  2299. substituteClassname(cvariable_type, tm);
  2300. Replaceall(tm, "$csinput", "value");
  2301. Replaceall(tm, "$imfuncname", intermediary_function_name);
  2302. Replaceall(tm, "$imcall", imcall);
  2303. excodeSubstitute(n, tm, "csvarin", variable_parm);
  2304. Printf(proxy_class_code, "%s", tm);
  2305. } else {
  2306. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(cvariable_type, 0));
  2307. }
  2308. } else {
  2309. // Getter method
  2310. if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
  2311. if (GetFlag(n, "feature:new"))
  2312. Replaceall(tm, "$owner", "true");
  2313. else
  2314. Replaceall(tm, "$owner", "false");
  2315. substituteClassname(t, tm);
  2316. Replaceall(tm, "$imfuncname", intermediary_function_name);
  2317. Replaceall(tm, "$imcall", imcall);
  2318. excodeSubstitute(n, tm, "csvarout", n);
  2319. Printf(proxy_class_code, "%s", tm);
  2320. } else {
  2321. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
  2322. }
  2323. }
  2324. } else {
  2325. // Normal function call
  2326. Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
  2327. Printv(proxy_class_code, function_code, NIL);
  2328. }
  2329. Delete(pre_code);
  2330. Delete(post_code);
  2331. Delete(terminator_code);
  2332. Delete(function_code);
  2333. Delete(return_type);
  2334. Delete(imcall);
  2335. }
  2336. /* ----------------------------------------------------------------------
  2337. * constructorHandler()
  2338. * ---------------------------------------------------------------------- */
  2339. virtual int constructorHandler(Node *n) {
  2340. ParmList *l = Getattr(n, "parms");
  2341. String *tm;
  2342. Parm *p;
  2343. int i;
  2344. String *function_code = NewString("");
  2345. String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the csin typemap has code in the pre or post attributes
  2346. String *helper_args = NewString("");
  2347. String *pre_code = NewString("");
  2348. String *post_code = NewString("");
  2349. String *terminator_code = NewString("");
  2350. String *im_return_type = NewString("");
  2351. bool feature_director = (parentNode(n) && Swig_directorclass(n));
  2352. Language::constructorHandler(n);
  2353. // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
  2354. if (Getattr(n, "overload:ignore"))
  2355. return SWIG_OK;
  2356. if (proxy_flag) {
  2357. String *overloaded_name = getOverloadedName(n);
  2358. String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
  2359. String *imcall = NewString("");
  2360. const String *csattributes = Getattr(n, "feature:cs:attributes");
  2361. if (csattributes) {
  2362. Printf(function_code, " %s\n", csattributes);
  2363. Printf(helper_code, " %s\n", csattributes);
  2364. }
  2365. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  2366. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  2367. tm = Getattr(n, "tmap:imtype"); // typemaps were attached earlier to the node
  2368. String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
  2369. if (imtypeout)
  2370. tm = imtypeout;
  2371. Printf(im_return_type, "%s", tm);
  2372. Printf(function_code, " %s %s(", methodmods, proxy_class_name);
  2373. Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
  2374. Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
  2375. /* Attach the non-standard typemaps to the parameter list */
  2376. Swig_typemap_attach_parms("in", l, NULL);
  2377. Swig_typemap_attach_parms("cstype", l, NULL);
  2378. Swig_typemap_attach_parms("csin", l, NULL);
  2379. emit_mark_varargs(l);
  2380. int gencomma = 0;
  2381. /* Output each parameter */
  2382. for (i = 0, p = l; p; i++) {
  2383. /* Ignored varargs */
  2384. if (checkAttribute(p, "varargs:ignore", "1")) {
  2385. p = nextSibling(p);
  2386. continue;
  2387. }
  2388. /* Ignored parameters */
  2389. if (checkAttribute(p, "tmap:in:numinputs", "0")) {
  2390. p = Getattr(p, "tmap:in:next");
  2391. continue;
  2392. }
  2393. SwigType *pt = Getattr(p, "type");
  2394. String *param_type = NewString("");
  2395. /* Get the C# parameter type */
  2396. if ((tm = Getattr(p, "tmap:cstype"))) {
  2397. substituteClassname(pt, tm);
  2398. const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
  2399. Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  2400. } else {
  2401. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
  2402. }
  2403. if (gencomma)
  2404. Printf(imcall, ", ");
  2405. String *arg = makeParameterName(n, p, i, false);
  2406. String *cshin = 0;
  2407. // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
  2408. if ((tm = Getattr(p, "tmap:csin"))) {
  2409. substituteClassname(pt, tm);
  2410. Replaceall(tm, "$csinput", arg);
  2411. String *pre = Getattr(p, "tmap:csin:pre");
  2412. if (pre) {
  2413. substituteClassname(pt, pre);
  2414. Replaceall(pre, "$csinput", arg);
  2415. if (Len(pre_code) > 0)
  2416. Printf(pre_code, "\n");
  2417. Printv(pre_code, pre, NIL);
  2418. }
  2419. String *post = Getattr(p, "tmap:csin:post");
  2420. if (post) {
  2421. substituteClassname(pt, post);
  2422. Replaceall(post, "$csinput", arg);
  2423. if (Len(post_code) > 0)
  2424. Printf(post_code, "\n");
  2425. Printv(post_code, post, NIL);
  2426. }
  2427. String *terminator = Getattr(p, "tmap:csin:terminator");
  2428. if (terminator) {
  2429. substituteClassname(pt, terminator);
  2430. Replaceall(terminator, "$csinput", arg);
  2431. if (Len(terminator_code) > 0)
  2432. Insert(terminator_code, 0, "\n");
  2433. Insert(terminator_code, 0, terminator);
  2434. }
  2435. cshin = Getattr(p, "tmap:csin:cshin");
  2436. if (cshin)
  2437. Replaceall(cshin, "$csinput", arg);
  2438. Printv(imcall, tm, NIL);
  2439. } else {
  2440. Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
  2441. }
  2442. /* Add parameter to proxy function */
  2443. if (gencomma) {
  2444. Printf(function_code, ", ");
  2445. Printf(helper_code, ", ");
  2446. Printf(helper_args, ", ");
  2447. }
  2448. Printf(function_code, "%s %s", param_type, arg);
  2449. Printf(helper_code, "%s %s", param_type, arg);
  2450. Printf(helper_args, "%s", cshin ? cshin : arg);
  2451. ++gencomma;
  2452. Delete(cshin);
  2453. Delete(arg);
  2454. Delete(param_type);
  2455. p = Getattr(p, "tmap:in:next");
  2456. }
  2457. Printf(imcall, ")");
  2458. Printf(function_code, ")");
  2459. Printf(helper_code, ")");
  2460. /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */
  2461. Hash *attributes = NewHash();
  2462. String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
  2463. String *construct_tm = Copy(typemapLookup(n, "csconstruct", typemap_lookup_type,
  2464. WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes));
  2465. if (construct_tm) {
  2466. if (!feature_director) {
  2467. Replaceall(construct_tm, "$directorconnect", "");
  2468. } else {
  2469. String *connect_attr = Getattr(attributes, "tmap:csconstruct:directorconnect");
  2470. if (connect_attr) {
  2471. Replaceall(construct_tm, "$directorconnect", connect_attr);
  2472. } else {
  2473. Swig_warning(WARN_CSHARP_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"csconstruct\" typemap.\n",
  2474. Getattr(n, "name"));
  2475. Replaceall(construct_tm, "$directorconnect", "");
  2476. }
  2477. }
  2478. Printv(function_code, " ", construct_tm, NIL);
  2479. }
  2480. excodeSubstitute(n, function_code, "csconstruct", attributes);
  2481. bool is_pre_code = Len(pre_code) > 0;
  2482. bool is_post_code = Len(post_code) > 0;
  2483. bool is_terminator_code = Len(terminator_code) > 0;
  2484. if (is_pre_code || is_post_code || is_terminator_code) {
  2485. Printf(helper_code, " {\n");
  2486. if (is_pre_code) {
  2487. Printv(helper_code, pre_code, "\n", NIL);
  2488. }
  2489. if (is_post_code) {
  2490. Printf(helper_code, " try {\n");
  2491. Printv(helper_code, " return ", imcall, ";\n", NIL);
  2492. Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
  2493. } else {
  2494. Printv(helper_code, " return ", imcall, ";", NIL);
  2495. }
  2496. if (is_terminator_code) {
  2497. Printv(helper_code, "\n", terminator_code, NIL);
  2498. }
  2499. Printf(helper_code, "\n }\n");
  2500. String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
  2501. String *im_outattributes = Getattr(n, "tmap:imtype:outattributes");
  2502. if (im_outattributes)
  2503. Printf(proxy_class_code, " %s\n", im_outattributes);
  2504. Printv(proxy_class_code, helper_code, "\n", NIL);
  2505. Replaceall(function_code, "$imcall", helper_name);
  2506. Delete(helper_name);
  2507. } else {
  2508. Replaceall(function_code, "$imcall", imcall);
  2509. }
  2510. Printv(proxy_class_code, function_code, "\n", NIL);
  2511. Delete(helper_args);
  2512. Delete(im_return_type);
  2513. Delete(pre_code);
  2514. Delete(post_code);
  2515. Delete(terminator_code);
  2516. Delete(construct_tm);
  2517. Delete(attributes);
  2518. Delete(overloaded_name);
  2519. Delete(imcall);
  2520. }
  2521. return SWIG_OK;
  2522. }
  2523. /* ----------------------------------------------------------------------
  2524. * destructorHandler()
  2525. * ---------------------------------------------------------------------- */
  2526. virtual int destructorHandler(Node *n) {
  2527. Language::destructorHandler(n);
  2528. String *symname = Getattr(n, "sym:name");
  2529. if (proxy_flag) {
  2530. Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
  2531. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  2532. if (methodmods)
  2533. Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
  2534. }
  2535. return SWIG_OK;
  2536. }
  2537. /* ----------------------------------------------------------------------
  2538. * membervariableHandler()
  2539. * ---------------------------------------------------------------------- */
  2540. virtual int membervariableHandler(Node *n) {
  2541. generate_property_declaration_flag = true;
  2542. variable_name = Getattr(n, "sym:name");
  2543. wrapping_member_flag = true;
  2544. variable_wrapper_flag = true;
  2545. Language::membervariableHandler(n);
  2546. wrapping_member_flag = false;
  2547. variable_wrapper_flag = false;
  2548. generate_property_declaration_flag = false;
  2549. Printf(proxy_class_code, "\n }\n\n");
  2550. return SWIG_OK;
  2551. }
  2552. /* ----------------------------------------------------------------------
  2553. * staticmembervariableHandler()
  2554. * ---------------------------------------------------------------------- */
  2555. virtual int staticmembervariableHandler(Node *n) {
  2556. bool static_const_member_flag = (Getattr(n, "value") == 0);
  2557. generate_property_declaration_flag = true;
  2558. variable_name = Getattr(n, "sym:name");
  2559. wrapping_member_flag = true;
  2560. static_flag = true;
  2561. Language::staticmembervariableHandler(n);
  2562. wrapping_member_flag = false;
  2563. static_flag = false;
  2564. generate_property_declaration_flag = false;
  2565. if (static_const_member_flag)
  2566. Printf(proxy_class_code, "\n }\n\n");
  2567. return SWIG_OK;
  2568. }
  2569. /* ----------------------------------------------------------------------
  2570. * memberconstantHandler()
  2571. * ---------------------------------------------------------------------- */
  2572. virtual int memberconstantHandler(Node *n) {
  2573. variable_name = Getattr(n, "sym:name");
  2574. wrapping_member_flag = true;
  2575. Language::memberconstantHandler(n);
  2576. wrapping_member_flag = false;
  2577. return SWIG_OK;
  2578. }
  2579. /* -----------------------------------------------------------------------------
  2580. * getOverloadedName()
  2581. * ----------------------------------------------------------------------------- */
  2582. String *getOverloadedName(Node *n) {
  2583. /* A C# HandleRef is used for all classes in the SWIG intermediary class.
  2584. * The intermediary class methods are thus mangled when overloaded to give
  2585. * a unique name. */
  2586. String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
  2587. if (Getattr(n, "sym:overloaded")) {
  2588. Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
  2589. }
  2590. return overloaded_name;
  2591. }
  2592. /* -----------------------------------------------------------------------------
  2593. * moduleClassFunctionHandler()
  2594. * ----------------------------------------------------------------------------- */
  2595. void moduleClassFunctionHandler(Node *n) {
  2596. SwigType *t = Getattr(n, "type");
  2597. ParmList *l = Getattr(n, "parms");
  2598. String *tm;
  2599. Parm *p;
  2600. Parm *last_parm = 0;
  2601. int i;
  2602. String *imcall = NewString("");
  2603. String *return_type = NewString("");
  2604. String *function_code = NewString("");
  2605. int num_arguments = 0;
  2606. String *overloaded_name = getOverloadedName(n);
  2607. String *func_name = NULL;
  2608. bool setter_flag = false;
  2609. String *pre_code = NewString("");
  2610. String *post_code = NewString("");
  2611. String *terminator_code = NewString("");
  2612. if (l) {
  2613. if (SwigType_type(Getattr(l, "type")) == T_VOID) {
  2614. l = nextSibling(l);
  2615. }
  2616. }
  2617. /* Attach the non-standard typemaps to the parameter list */
  2618. Swig_typemap_attach_parms("cstype", l, NULL);
  2619. Swig_typemap_attach_parms("csin", l, NULL);
  2620. /* Get return types */
  2621. if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
  2622. String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
  2623. if (cstypeout)
  2624. tm = cstypeout;
  2625. substituteClassname(t, tm);
  2626. Printf(return_type, "%s", tm);
  2627. } else {
  2628. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
  2629. }
  2630. /* Change function name for global variables */
  2631. if (proxy_flag && global_variable_flag) {
  2632. // Capitalize the first letter in the variable to create the getter/setter function name
  2633. func_name = NewString("");
  2634. setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
  2635. if (setter_flag)
  2636. Printf(func_name, "set");
  2637. else
  2638. Printf(func_name, "get");
  2639. Putc(toupper((int) *Char(variable_name)), func_name);
  2640. Printf(func_name, "%s", Char(variable_name) + 1);
  2641. if (setter_flag)
  2642. Swig_typemap_attach_parms("csvarin", l, NULL);
  2643. } else {
  2644. func_name = Copy(Getattr(n, "sym:name"));
  2645. }
  2646. /* Start generating the function */
  2647. const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
  2648. if (outattributes)
  2649. Printf(function_code, " %s\n", outattributes);
  2650. const String *csattributes = Getattr(n, "feature:cs:attributes");
  2651. if (csattributes)
  2652. Printf(function_code, " %s\n", csattributes);
  2653. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  2654. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  2655. Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
  2656. Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
  2657. /* Get number of required and total arguments */
  2658. num_arguments = emit_num_arguments(l);
  2659. bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
  2660. int gencomma = 0;
  2661. /* Output each parameter */
  2662. for (i = 0, p = l; i < num_arguments; i++) {
  2663. /* Ignored parameters */
  2664. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  2665. p = Getattr(p, "tmap:in:next");
  2666. }
  2667. SwigType *pt = Getattr(p, "type");
  2668. String *param_type = NewString("");
  2669. last_parm = p;
  2670. /* Get the C# parameter type */
  2671. if ((tm = Getattr(p, "tmap:cstype"))) {
  2672. substituteClassname(pt, tm);
  2673. const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
  2674. Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  2675. } else {
  2676. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
  2677. }
  2678. if (gencomma)
  2679. Printf(imcall, ", ");
  2680. String *arg = makeParameterName(n, p, i, global_or_member_variable);
  2681. // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
  2682. if ((tm = Getattr(p, "tmap:csin"))) {
  2683. substituteClassname(pt, tm);
  2684. Replaceall(tm, "$csinput", arg);
  2685. String *pre = Getattr(p, "tmap:csin:pre");
  2686. if (pre) {
  2687. substituteClassname(pt, pre);
  2688. Replaceall(pre, "$csinput", arg);
  2689. if (Len(pre_code) > 0)
  2690. Printf(pre_code, "\n");
  2691. Printv(pre_code, pre, NIL);
  2692. }
  2693. String *post = Getattr(p, "tmap:csin:post");
  2694. if (post) {
  2695. substituteClassname(pt, post);
  2696. Replaceall(post, "$csinput", arg);
  2697. if (Len(post_code) > 0)
  2698. Printf(post_code, "\n");
  2699. Printv(post_code, post, NIL);
  2700. }
  2701. String *terminator = Getattr(p, "tmap:csin:terminator");
  2702. if (terminator) {
  2703. substituteClassname(pt, terminator);
  2704. Replaceall(terminator, "$csinput", arg);
  2705. if (Len(terminator_code) > 0)
  2706. Insert(terminator_code, 0, "\n");
  2707. Insert(terminator_code, 0, terminator);
  2708. }
  2709. Printv(imcall, tm, NIL);
  2710. } else {
  2711. Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
  2712. }
  2713. /* Add parameter to module class function */
  2714. if (gencomma >= 2)
  2715. Printf(function_code, ", ");
  2716. gencomma = 2;
  2717. Printf(function_code, "%s %s", param_type, arg);
  2718. p = Getattr(p, "tmap:in:next");
  2719. Delete(arg);
  2720. Delete(param_type);
  2721. }
  2722. Printf(imcall, ")");
  2723. Printf(function_code, ")");
  2724. // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class)
  2725. if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
  2726. excodeSubstitute(n, tm, "csout", n);
  2727. bool is_pre_code = Len(pre_code) > 0;
  2728. bool is_post_code = Len(post_code) > 0;
  2729. bool is_terminator_code = Len(terminator_code) > 0;
  2730. if (is_pre_code || is_post_code || is_terminator_code) {
  2731. Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
  2732. if (is_post_code) {
  2733. Insert(tm, 0, "\n try ");
  2734. Printv(tm, " finally {\n", post_code, "\n }", NIL);
  2735. } else {
  2736. Insert(tm, 0, "\n ");
  2737. }
  2738. if (is_pre_code) {
  2739. Insert(tm, 0, pre_code);
  2740. Insert(tm, 0, "\n");
  2741. }
  2742. if (is_terminator_code) {
  2743. Printv(tm, "\n", terminator_code, NIL);
  2744. }
  2745. Insert(tm, 0, "{");
  2746. Printf(tm, "\n }");
  2747. }
  2748. if (GetFlag(n, "feature:new"))
  2749. Replaceall(tm, "$owner", "true");
  2750. else
  2751. Replaceall(tm, "$owner", "false");
  2752. substituteClassname(t, tm);
  2753. Replaceall(tm, "$imfuncname", overloaded_name);
  2754. Replaceall(tm, "$imcall", imcall);
  2755. } else {
  2756. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
  2757. }
  2758. if (proxy_flag && global_variable_flag) {
  2759. // Properties
  2760. if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
  2761. // Get the C# variable type - obtained differently depending on whether a setter is required.
  2762. String *variable_type = return_type;
  2763. if (setter_flag) {
  2764. p = last_parm; // (last parameter is the only parameter for properties)
  2765. SwigType *pt = Getattr(p, "type");
  2766. if ((tm = Getattr(p, "tmap:cstype"))) {
  2767. substituteClassname(pt, tm);
  2768. String *cstypeout = Getattr(p, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
  2769. variable_type = cstypeout ? cstypeout : tm;
  2770. } else {
  2771. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
  2772. }
  2773. }
  2774. const String *csattributes = Getattr(n, "feature:cs:attributes");
  2775. if (csattributes)
  2776. Printf(module_class_code, " %s\n", csattributes);
  2777. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  2778. if (!methodmods)
  2779. methodmods = (is_public(n) ? public_string : protected_string);
  2780. Printf(module_class_code, " %s static %s %s {", methodmods, variable_type, variable_name);
  2781. }
  2782. generate_property_declaration_flag = false;
  2783. if (setter_flag) {
  2784. // Setter method
  2785. p = last_parm; // (last parameter is the only parameter for properties)
  2786. SwigType *pt = Getattr(p, "type");
  2787. if ((tm = Getattr(p, "tmap:csvarin"))) {
  2788. substituteClassname(pt, tm);
  2789. Replaceall(tm, "$csinput", "value");
  2790. Replaceall(tm, "$imfuncname", overloaded_name);
  2791. Replaceall(tm, "$imcall", imcall);
  2792. excodeSubstitute(n, tm, "csvarin", p);
  2793. Printf(module_class_code, "%s", tm);
  2794. } else {
  2795. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
  2796. }
  2797. } else {
  2798. // Getter method
  2799. if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
  2800. if (GetFlag(n, "feature:new"))
  2801. Replaceall(tm, "$owner", "true");
  2802. else
  2803. Replaceall(tm, "$owner", "false");
  2804. substituteClassname(t, tm);
  2805. Replaceall(tm, "$imfuncname", overloaded_name);
  2806. Replaceall(tm, "$imcall", imcall);
  2807. excodeSubstitute(n, tm, "csvarout", n);
  2808. Printf(module_class_code, "%s", tm);
  2809. } else {
  2810. Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
  2811. }
  2812. }
  2813. } else {
  2814. // Normal function call
  2815. Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
  2816. Printv(module_class_code, function_code, NIL);
  2817. }
  2818. Delete(pre_code);
  2819. Delete(post_code);
  2820. Delete(terminator_code);
  2821. Delete(function_code);
  2822. Delete(return_type);
  2823. Delete(imcall);
  2824. Delete(func_name);
  2825. }
  2826. /*----------------------------------------------------------------------
  2827. * replaceSpecialVariables()
  2828. *--------------------------------------------------------------------*/
  2829. virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
  2830. (void)method;
  2831. SwigType *type = Getattr(parm, "type");
  2832. substituteClassname(type, tm);
  2833. }
  2834. /*----------------------------------------------------------------------
  2835. * decodeEnumFeature()
  2836. * Decode the possible enum features, which are one of:
  2837. * %csenum(simple)
  2838. * %csenum(typeunsafe) - default
  2839. * %csenum(typesafe)
  2840. * %csenum(proper)
  2841. *--------------------------------------------------------------------*/
  2842. EnumFeature decodeEnumFeature(Node *n) {
  2843. EnumFeature enum_feature = TypeunsafeEnum;
  2844. String *feature = Getattr(n, "feature:cs:enum");
  2845. if (feature) {
  2846. if (Cmp(feature, "simple") == 0)
  2847. enum_feature = SimpleEnum;
  2848. else if (Cmp(feature, "typesafe") == 0)
  2849. enum_feature = TypesafeEnum;
  2850. else if (Cmp(feature, "proper") == 0)
  2851. enum_feature = ProperEnum;
  2852. }
  2853. return enum_feature;
  2854. }
  2855. /* -----------------------------------------------------------------------
  2856. * enumValue()
  2857. * This method will return a string with an enum value to use in C# generated
  2858. * code. If the %csconst feature is not used, the string will contain the intermediary
  2859. * class call to obtain the enum value. The intermediary class and PINVOKE methods to obtain
  2860. * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
  2861. * is one and hopefully it will compile as C# code - e.g. 20 as in: enum E{e=20};
  2862. * The %csconstvalue feature overrides all other ways to generate the constant value.
  2863. * The caller must delete memory allocated for the returned string.
  2864. * ------------------------------------------------------------------------ */
  2865. String *enumValue(Node *n) {
  2866. String *symname = Getattr(n, "sym:name");
  2867. // Check for the %csconstvalue feature
  2868. String *value = Getattr(n, "feature:cs:constvalue");
  2869. if (!value) {
  2870. // The %csconst feature determines how the constant value is obtained
  2871. int const_feature_flag = GetFlag(n, "feature:cs:const");
  2872. if (const_feature_flag) {
  2873. // Use the C syntax to make a true C# constant and hope that it compiles as C# code
  2874. value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
  2875. } else {
  2876. String *newsymname = 0;
  2877. if (!getCurrentClass() || !proxy_flag) {
  2878. String *enumClassPrefix = getEnumClassPrefix();
  2879. if (enumClassPrefix) {
  2880. // A global scoped enum
  2881. newsymname = Swig_name_member(0, enumClassPrefix, symname);
  2882. symname = newsymname;
  2883. }
  2884. }
  2885. // Get the enumvalue from a PINVOKE call
  2886. if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
  2887. // Strange hack to change the name
  2888. Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
  2889. constantWrapper(n);
  2890. value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  2891. } else {
  2892. memberconstantHandler(n);
  2893. value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
  2894. }
  2895. }
  2896. }
  2897. return value;
  2898. }
  2899. /* -----------------------------------------------------------------------------
  2900. * getEnumName()
  2901. * ----------------------------------------------------------------------------- */
  2902. String *getEnumName(SwigType *t) {
  2903. Node *enumname = NULL;
  2904. Node *n = enumLookup(t);
  2905. if (n) {
  2906. enumname = Getattr(n, "enumname");
  2907. if (!enumname) {
  2908. String *symname = Getattr(n, "sym:name");
  2909. if (symname) {
  2910. // Add in class scope when referencing enum if not a global enum
  2911. String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
  2912. String *proxyname = 0;
  2913. if (scopename_prefix) {
  2914. proxyname = getProxyName(scopename_prefix);
  2915. }
  2916. if (proxyname) {
  2917. enumname = NewStringf("%s.%s", proxyname, symname);
  2918. } else {
  2919. // global enum or enum in a namespace
  2920. String *nspace = Getattr(n, "sym:nspace");
  2921. if (nspace) {
  2922. if (namespce)
  2923. enumname = NewStringf("%s.%s.%s", namespce, nspace, symname);
  2924. else
  2925. enumname = NewStringf("%s.%s", nspace, symname);
  2926. } else {
  2927. enumname = Copy(symname);
  2928. }
  2929. }
  2930. Setattr(n, "enumname", enumname);
  2931. Delete(enumname);
  2932. Delete(scopename_prefix);
  2933. }
  2934. }
  2935. }
  2936. return enumname;
  2937. }
  2938. /* -----------------------------------------------------------------------------
  2939. * substituteClassname()
  2940. *
  2941. * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
  2942. * that SWIG knows about. Also substitutes enums with enum name.
  2943. * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
  2944. * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
  2945. * Inputs:
  2946. * pt - parameter type
  2947. * tm - typemap contents that might contain the special variable to be replaced
  2948. * Outputs:
  2949. * tm - typemap contents complete with the special variable substitution
  2950. * Return:
  2951. * substitution_performed - flag indicating if a substitution was performed
  2952. * ----------------------------------------------------------------------------- */
  2953. bool substituteClassname(SwigType *pt, String *tm) {
  2954. bool substitution_performed = false;
  2955. SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
  2956. SwigType *strippedtype = SwigType_strip_qualifiers(type);
  2957. if (Strstr(tm, "$csclassname")) {
  2958. SwigType *classnametype = Copy(strippedtype);
  2959. substituteClassnameSpecialVariable(classnametype, tm, "$csclassname");
  2960. substitution_performed = true;
  2961. Delete(classnametype);
  2962. }
  2963. if (Strstr(tm, "$*csclassname")) {
  2964. SwigType *classnametype = Copy(strippedtype);
  2965. Delete(SwigType_pop(classnametype));
  2966. if (Len(classnametype) > 0) {
  2967. substituteClassnameSpecialVariable(classnametype, tm, "$*csclassname");
  2968. substitution_performed = true;
  2969. }
  2970. Delete(classnametype);
  2971. }
  2972. if (Strstr(tm, "$&csclassname")) {
  2973. SwigType *classnametype = Copy(strippedtype);
  2974. SwigType_add_pointer(classnametype);
  2975. substituteClassnameSpecialVariable(classnametype, tm, "$&csclassname");
  2976. substitution_performed = true;
  2977. Delete(classnametype);
  2978. }
  2979. if (Strstr(tm, "$csinterfacename")) {
  2980. SwigType *interfacenametype = Copy(strippedtype);
  2981. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$csinterfacename", true);
  2982. substitution_performed = true;
  2983. Delete(interfacenametype);
  2984. }
  2985. if (Strstr(tm, "$*csinterfacename")) {
  2986. SwigType *interfacenametype = Copy(strippedtype);
  2987. Delete(SwigType_pop(interfacenametype));
  2988. if (Len(interfacenametype) > 0) {
  2989. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*csinterfacename", true);
  2990. substitution_performed = true;
  2991. }
  2992. Delete(interfacenametype);
  2993. }
  2994. if (Strstr(tm, "$&csinterfacename")) {
  2995. SwigType *interfacenametype = Copy(strippedtype);
  2996. SwigType_add_pointer(interfacenametype);
  2997. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&csinterfacename", true);
  2998. substitution_performed = true;
  2999. Delete(interfacenametype);
  3000. }
  3001. if (Strstr(tm, "$interfacename")) {
  3002. SwigType *interfacenametype = Copy(strippedtype);
  3003. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", false);
  3004. substitution_performed = true;
  3005. Delete(interfacenametype);
  3006. }
  3007. if (Strstr(tm, "$*interfacename")) {
  3008. SwigType *interfacenametype = Copy(strippedtype);
  3009. Delete(SwigType_pop(interfacenametype));
  3010. if (Len(interfacenametype) > 0) {
  3011. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", false);
  3012. substitution_performed = true;
  3013. }
  3014. Delete(interfacenametype);
  3015. }
  3016. if (Strstr(tm, "$&interfacename")) {
  3017. SwigType *interfacenametype = Copy(strippedtype);
  3018. SwigType_add_pointer(interfacenametype);
  3019. substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", false);
  3020. substitution_performed = true;
  3021. Delete(interfacenametype);
  3022. }
  3023. Delete(strippedtype);
  3024. Delete(type);
  3025. return substitution_performed;
  3026. }
  3027. /* -----------------------------------------------------------------------------
  3028. * substituteClassnameSpecialVariable()
  3029. * ----------------------------------------------------------------------------- */
  3030. void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
  3031. String *replacementname;
  3032. if (SwigType_isenum(classnametype)) {
  3033. String *enumname = getEnumName(classnametype);
  3034. if (enumname) {
  3035. replacementname = Copy(enumname);
  3036. } else {
  3037. bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
  3038. if (anonymous_enum) {
  3039. replacementname = NewString("int");
  3040. } else {
  3041. // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
  3042. replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
  3043. Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
  3044. Setattr(swig_types_hash, replacementname, classnametype);
  3045. }
  3046. }
  3047. } else {
  3048. String *classname = getProxyName(classnametype); // getProxyName() works for pointers to classes too
  3049. if (classname) {
  3050. replacementname = Copy(classname);
  3051. } else {
  3052. // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
  3053. replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
  3054. // Add to hash table so that the type wrapper classes can be created later
  3055. Setattr(swig_types_hash, replacementname, classnametype);
  3056. }
  3057. }
  3058. Replaceall(tm, classnamespecialvariable, replacementname);
  3059. Delete(replacementname);
  3060. }
  3061. /* -----------------------------------------------------------------------------
  3062. * substituteInterfacenameSpecialVariable()
  3063. * ----------------------------------------------------------------------------- */
  3064. void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool qualified) {
  3065. String *interfacename = getInterfaceName(interfacenametype, qualified);
  3066. if (interfacename) {
  3067. String *replacementname = Copy(interfacename);
  3068. Replaceall(tm, interfacenamespecialvariable, replacementname);
  3069. Delete(replacementname);
  3070. }
  3071. }
  3072. /* -----------------------------------------------------------------------------
  3073. * emitTypeWrapperClass()
  3074. * ----------------------------------------------------------------------------- */
  3075. void emitTypeWrapperClass(String *classname, SwigType *type) {
  3076. Node *n = NewHash();
  3077. Setfile(n, input_file);
  3078. Setline(n, line_number);
  3079. String *swigtype = NewString("");
  3080. File *f_swigtype = getOutputFile(SWIG_output_directory(), classname);
  3081. addOpenNamespace(0, f_swigtype);
  3082. // Pure C# baseclass and interfaces
  3083. const String *pure_baseclass = typemapLookup(n, "csbase", type, WARN_NONE);
  3084. const String *pure_interfaces = typemapLookup(n, "csinterfaces", type, WARN_NONE);
  3085. // Emit the class
  3086. Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE), // Import statements
  3087. "\n", NIL);
  3088. // Class attributes
  3089. const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE);
  3090. if (csattributes && *Char(csattributes))
  3091. Printf(swigtype, "%s\n", csattributes);
  3092. Printv(swigtype, typemapLookup(n, "csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
  3093. " $csclassname", // Class name and base class
  3094. (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
  3095. ", " : "", pure_interfaces, " {", typemapLookup(n, "csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
  3096. typemapLookup(n, "cscode", type, WARN_NONE), // extra C# code
  3097. "}\n", NIL);
  3098. Replaceall(swigtype, "$csclassname", classname);
  3099. Replaceall(swigtype, "$module", module_class_name);
  3100. Replaceall(swigtype, "$imclassname", imclass_name);
  3101. Replaceall(swigtype, "$dllimport", dllimport);
  3102. // For unknown enums
  3103. Replaceall(swigtype, "$enumvalues", "");
  3104. Printv(f_swigtype, swigtype, NIL);
  3105. addCloseNamespace(0, f_swigtype);
  3106. if (f_swigtype != f_single_out)
  3107. Delete(f_swigtype);
  3108. f_swigtype = NULL;
  3109. Delete(swigtype);
  3110. Delete(n);
  3111. }
  3112. /* -----------------------------------------------------------------------------
  3113. * typemapLookup()
  3114. * n - for input only and must contain info for Getfile(n) and Getline(n) to work
  3115. * tmap_method - typemap method name
  3116. * type - typemap type to lookup
  3117. * warning - warning number to issue if no typemaps found
  3118. * typemap_attributes - the typemap attributes are attached to this node and will
  3119. * also be used for temporary storage if non null
  3120. * return is never NULL, unlike Swig_typemap_lookup()
  3121. * ----------------------------------------------------------------------------- */
  3122. const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
  3123. Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
  3124. Setattr(node, "type", type);
  3125. Setfile(node, Getfile(n));
  3126. Setline(node, Getline(n));
  3127. const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
  3128. if (!tm) {
  3129. tm = empty_string;
  3130. if (warning != WARN_NONE)
  3131. Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
  3132. }
  3133. if (!typemap_attributes)
  3134. Delete(node);
  3135. return tm;
  3136. }
  3137. /* -----------------------------------------------------------------------------
  3138. * typemapExists()
  3139. * n - for input only and must contain info for Getfile(n) and Getline(n) to work
  3140. * tmap_method - typemap method name
  3141. * type - typemap type to lookup
  3142. * returns found typemap or NULL if not found
  3143. * ----------------------------------------------------------------------------- */
  3144. const String *typemapExists(Node *n, const_String_or_char_ptr tmap_method, SwigType *type) {
  3145. Node *node = NewHash();
  3146. Setattr(node, "type", type);
  3147. Setfile(node, Getfile(n));
  3148. Setline(node, Getline(n));
  3149. const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
  3150. Delete(node);
  3151. return tm;
  3152. }
  3153. /* -----------------------------------------------------------------------------
  3154. * canThrow()
  3155. * Determine whether the code in the typemap can throw a C# exception.
  3156. * If so, note it for later when excodeSubstitute() is called.
  3157. * ----------------------------------------------------------------------------- */
  3158. void canThrow(Node *n, const String *typemap, Node *parameter) {
  3159. String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
  3160. String *canthrow = Getattr(parameter, canthrow_attribute);
  3161. if (canthrow)
  3162. Setattr(n, "csharp:canthrow", "1");
  3163. Delete(canthrow_attribute);
  3164. }
  3165. /* -----------------------------------------------------------------------------
  3166. * excodeSubstitute()
  3167. * If a method can throw a C# exception, additional exception code is added to
  3168. * check for the pending exception so that it can then throw the exception. The
  3169. * $excode special variable is replaced by the exception code in the excode
  3170. * typemap attribute.
  3171. * ----------------------------------------------------------------------------- */
  3172. void excodeSubstitute(Node *n, String *code, const String *typemap, Node *parameter) {
  3173. String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
  3174. String *excode = Getattr(parameter, excode_attribute);
  3175. if (Getattr(n, "csharp:canthrow")) {
  3176. int count = Replaceall(code, "$excode", excode);
  3177. if (count < 1 || !excode) {
  3178. Swig_warning(WARN_CSHARP_EXCODE, input_file, line_number,
  3179. "C# exception may not be thrown - no $excode or excode attribute in '%s' typemap.\n", typemap);
  3180. }
  3181. } else {
  3182. Replaceall(code, "$excode", empty_string);
  3183. }
  3184. Delete(excode_attribute);
  3185. }
  3186. /* -----------------------------------------------------------------------------
  3187. * addOpenNamespace()
  3188. * ----------------------------------------------------------------------------- */
  3189. void addOpenNamespace(const String *nspace, File *file) {
  3190. if (namespce || nspace) {
  3191. Printf(file, "namespace ");
  3192. if (namespce)
  3193. Printv(file, namespce, nspace ? "." : "", NIL);
  3194. if (nspace)
  3195. Printv(file, nspace, NIL);
  3196. Printf(file, " {\n");
  3197. }
  3198. }
  3199. /* -----------------------------------------------------------------------------
  3200. * addCloseNamespace()
  3201. * ----------------------------------------------------------------------------- */
  3202. void addCloseNamespace(const String *nspace, File *file) {
  3203. if (namespce || nspace)
  3204. Printf(file, "\n}\n");
  3205. }
  3206. /* -----------------------------------------------------------------------------
  3207. * outputDirectory()
  3208. *
  3209. * Return the directory to use for generating C# classes/enums and create the
  3210. * subdirectory (does not create if language specific outdir does not exist).
  3211. * ----------------------------------------------------------------------------- */
  3212. String *outputDirectory(String *nspace) {
  3213. String *output_directory = Copy(SWIG_output_directory());
  3214. if (nspace) {
  3215. String *nspace_subdirectory = Copy(nspace);
  3216. Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
  3217. String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
  3218. if (newdir_error) {
  3219. Printf(stderr, "%s\n", newdir_error);
  3220. Delete(newdir_error);
  3221. Exit(EXIT_FAILURE);
  3222. }
  3223. Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
  3224. Delete(nspace_subdirectory);
  3225. }
  3226. return output_directory;
  3227. }
  3228. /*----------------------------------------------------------------------
  3229. * Start of director methods
  3230. *--------------------------------------------------------------------*/
  3231. #if 0
  3232. /*----------------------------------------------------------------------
  3233. * emitDirectorUpcalls()
  3234. *--------------------------------------------------------------------*/
  3235. void emitDirectorUpcalls() {
  3236. if (n_dmethods) {
  3237. Wrapper *w = NewWrapper();
  3238. String *dmethod_data = NewString("");
  3239. int n_methods = 0;
  3240. Iterator udata_iter;
  3241. udata_iter = First(dmethods_seq);
  3242. while (udata_iter.item) {
  3243. UpcallData *udata = udata_iter.item;
  3244. Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
  3245. ++n_methods;
  3246. udata_iter = Next(udata_iter);
  3247. if (udata_iter.item)
  3248. Putc(',', dmethod_data);
  3249. Putc('\n', dmethod_data);
  3250. }
  3251. Wrapper_print(w, f_wrappers);
  3252. Delete(dmethod_data);
  3253. Delete(swig_module_init);
  3254. DelWrapper(w);
  3255. }
  3256. }
  3257. #endif
  3258. /*----------------------------------------------------------------------
  3259. * emitDirectorExtraMethods()
  3260. *
  3261. * This is where the director connect method is generated.
  3262. *--------------------------------------------------------------------*/
  3263. void emitDirectorExtraMethods(Node *n) {
  3264. if (!Swig_directorclass(n))
  3265. return;
  3266. // Output the director connect method:
  3267. String *norm_name = SwigType_namestr(Getattr(n, "name"));
  3268. String *dirclassname = directorClassName(n);
  3269. String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
  3270. String *wname = Swig_name_wrapper(swig_director_connect);
  3271. String *sym_name = Getattr(n, "sym:name");
  3272. String *qualified_classname = Copy(sym_name);
  3273. String *nspace = getNSpace();
  3274. String *dirClassName = directorClassName(n);
  3275. String *smartptr = Getattr(n, "feature:smartptr");
  3276. if (!GetFlag(n, "feature:flatnested")) {
  3277. for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
  3278. Push(qualified_classname, ".");
  3279. Push(qualified_classname, Getattr(outer_class, "sym:name"));
  3280. }
  3281. }
  3282. if (nspace)
  3283. Insert(qualified_classname, 0, NewStringf("%s.", nspace));
  3284. Printv(imclass_class_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
  3285. Printf(imclass_class_code, " public static extern void %s(global::System.Runtime.InteropServices.HandleRef jarg1", swig_director_connect);
  3286. Wrapper *code_wrap = NewWrapper();
  3287. Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL %s(void *objarg", wname);
  3288. if (smartptr) {
  3289. Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", smartptr, smartptr);
  3290. Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
  3291. Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
  3292. Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
  3293. } else {
  3294. Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
  3295. Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
  3296. }
  3297. Printf(code_wrap->code, " director->swig_connect_director(");
  3298. for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  3299. UpcallData *udata = Getitem(dmethods_seq, i);
  3300. String *methid = Getattr(udata, "class_methodidx");
  3301. Printf(code_wrap->def, ", ");
  3302. if (i != first_class_dmethod)
  3303. Printf(code_wrap->code, ", ");
  3304. Printf(code_wrap->def, "%s::SWIG_Callback%s_t callback%s", dirclassname, methid, methid);
  3305. Printf(code_wrap->code, "callback%s", methid);
  3306. Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", qualified_classname, sym_name, methid, methid);
  3307. }
  3308. Printf(code_wrap->def, ") {\n");
  3309. Printf(code_wrap->code, ");\n");
  3310. Printf(imclass_class_code, ");\n");
  3311. Printf(code_wrap->code, "}\n");
  3312. Wrapper_print(code_wrap, f_wrappers);
  3313. DelWrapper(code_wrap);
  3314. Delete(wname);
  3315. Delete(swig_director_connect);
  3316. Delete(qualified_classname);
  3317. Delete(dirclassname);
  3318. }
  3319. /* ---------------------------------------------------------------
  3320. * classDirectorMethod()
  3321. *
  3322. * Emit a virtual director method to pass a method call on to the
  3323. * underlying C# object.
  3324. *
  3325. * --------------------------------------------------------------- */
  3326. int classDirectorMethod(Node *n, Node *parent, String *super) {
  3327. String *classname = Getattr(parent, "sym:name");
  3328. String *c_classname = Getattr(parent, "name");
  3329. String *name = Getattr(n, "name");
  3330. String *symname = Getattr(n, "sym:name");
  3331. SwigType *returntype = Getattr(n, "type");
  3332. String *overloaded_name = getOverloadedName(n);
  3333. String *storage = Getattr(n, "storage");
  3334. String *value = Getattr(n, "value");
  3335. String *decl = Getattr(n, "decl");
  3336. String *declaration = NewString("");
  3337. String *pre_code = NewString("");
  3338. String *post_code = NewString("");
  3339. String *terminator_code = NewString("");
  3340. String *tm;
  3341. Parm *p;
  3342. int i;
  3343. Wrapper *w = NewWrapper();
  3344. ParmList *l = Getattr(n, "parms");
  3345. bool is_void = !(Cmp(returntype, "void"));
  3346. String *qualified_return = 0;
  3347. bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
  3348. int status = SWIG_OK;
  3349. bool output_director = true;
  3350. String *dirclassname = directorClassName(parent);
  3351. String *qualified_name = NewStringf("%s::%s", dirclassname, name);
  3352. SwigType *c_ret_type = NULL;
  3353. String *jupcall_args = NewString("");
  3354. String *imclass_dmethod;
  3355. String *callback_typedef_parms = NewString("");
  3356. String *delegate_parms = NewString("");
  3357. String *proxy_method_types = NewString("");
  3358. String *callback_def = NewString("");
  3359. String *callback_code = NewString("");
  3360. String *imcall_args = NewString("");
  3361. bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
  3362. // Kludge Alert: functionWrapper sets sym:overload properly, but it
  3363. // isn't at this point, so we have to manufacture it ourselves. At least
  3364. // we're consistent with the sym:overload name in functionWrapper. (?? when
  3365. // does the overloaded method name get set?)
  3366. imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name));
  3367. qualified_return = SwigType_rcaststr(returntype, "c_result");
  3368. if (!is_void && (!ignored_method || pure_virtual)) {
  3369. if (!SwigType_isclass(returntype)) {
  3370. if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
  3371. String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
  3372. Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
  3373. Delete(construct_result);
  3374. } else {
  3375. String *base_typename = SwigType_base(returntype);
  3376. String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
  3377. Symtab *symtab = Getattr(n, "sym:symtab");
  3378. Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
  3379. if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
  3380. /* initialize pointers to something sane. Same for abstract
  3381. classes when a reference is returned. */
  3382. Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
  3383. } else {
  3384. /* If returning a reference, initialize the pointer to a sane
  3385. default - if a C# exception occurs, then the pointer returns
  3386. something other than a NULL-initialized reference. */
  3387. SwigType *noref_type = SwigType_del_reference(Copy(returntype));
  3388. String *noref_ltype = SwigType_lstr(noref_type, 0);
  3389. String *return_ltype = SwigType_lstr(returntype, 0);
  3390. Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
  3391. Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
  3392. Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
  3393. Printf(w->code, "c_result = &result_default;\n");
  3394. Delete(return_ltype);
  3395. Delete(noref_ltype);
  3396. Delete(noref_type);
  3397. }
  3398. Delete(base_typename);
  3399. Delete(resolved_typename);
  3400. }
  3401. } else {
  3402. SwigType *vt;
  3403. vt = cplus_value_type(returntype);
  3404. if (!vt) {
  3405. Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
  3406. } else {
  3407. Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
  3408. Delete(vt);
  3409. }
  3410. }
  3411. }
  3412. /* Create the intermediate class wrapper */
  3413. tm = Swig_typemap_lookup("imtype", n, "", 0);
  3414. if (tm) {
  3415. String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
  3416. if (imtypeout)
  3417. tm = imtypeout;
  3418. const String *im_directoroutattributes = Getattr(n, "tmap:imtype:directoroutattributes");
  3419. if (im_directoroutattributes) {
  3420. Printf(callback_def, " %s\n", im_directoroutattributes);
  3421. if (!ignored_method)
  3422. Printf(director_delegate_definitions, " %s\n", im_directoroutattributes);
  3423. }
  3424. Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name);
  3425. if (!ignored_method) {
  3426. const String *csdirectordelegatemodifiers = Getattr(n, "feature:csdirectordelegatemodifiers");
  3427. String *modifiers = (csdirectordelegatemodifiers ? NewStringf("%s%s", csdirectordelegatemodifiers, Len(csdirectordelegatemodifiers) > 0 ? " " : "") : NewStringf("public "));
  3428. Printf(director_delegate_definitions, " %sdelegate %s", modifiers, tm);
  3429. Delete(modifiers);
  3430. }
  3431. } else {
  3432. Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
  3433. }
  3434. if ((c_ret_type = Swig_typemap_lookup("ctype", n, "", 0))) {
  3435. if (!is_void && !ignored_method) {
  3436. String *jretval_decl = NewStringf("%s jresult", c_ret_type);
  3437. Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
  3438. Delete(jretval_decl);
  3439. }
  3440. } else {
  3441. Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
  3442. SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3443. output_director = false;
  3444. }
  3445. Swig_director_parms_fixup(l);
  3446. /* Attach the standard typemaps */
  3447. Swig_typemap_attach_parms("out", l, 0);
  3448. Swig_typemap_attach_parms("ctype", l, 0);
  3449. Swig_typemap_attach_parms("imtype", l, 0);
  3450. Swig_typemap_attach_parms("cstype", l, 0);
  3451. Swig_typemap_attach_parms("directorin", l, w);
  3452. Swig_typemap_attach_parms("csdirectorin", l, 0);
  3453. Swig_typemap_attach_parms("directorargout", l, w);
  3454. /* Preamble code */
  3455. if (!ignored_method)
  3456. Printf(w->code, "if (!swig_callback%s) {\n", overloaded_name);
  3457. if (!pure_virtual) {
  3458. String *super_call = Swig_method_call(super, l);
  3459. if (is_void) {
  3460. Printf(w->code, "%s;\n", super_call);
  3461. if (!ignored_method)
  3462. Printf(w->code, "return;\n");
  3463. } else {
  3464. Printf(w->code, "return %s;\n", super_call);
  3465. }
  3466. Delete(super_call);
  3467. } else {
  3468. Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
  3469. if (!is_void)
  3470. Printf(w->code, "return %s;", qualified_return);
  3471. else if (!ignored_method)
  3472. Printf(w->code, "return;\n");
  3473. }
  3474. if (!ignored_method)
  3475. Printf(w->code, "} else {\n");
  3476. /* Go through argument list, convert from native to C# */
  3477. for (i = 0, p = l; p; ++i) {
  3478. /* Is this superfluous? */
  3479. while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
  3480. p = Getattr(p, "tmap:directorin:next");
  3481. }
  3482. SwigType *pt = Getattr(p, "type");
  3483. String *ln = makeParameterName(n, p, i, false);
  3484. String *c_param_type = NULL;
  3485. String *c_decl = NewString("");
  3486. String *arg = NewString("");
  3487. Printf(arg, "j%s", ln);
  3488. /* And add to the upcall args */
  3489. if (i > 0)
  3490. Printf(jupcall_args, ", ");
  3491. Printf(jupcall_args, "%s", arg);
  3492. /* Get parameter's intermediary C type */
  3493. if ((c_param_type = Getattr(p, "tmap:ctype"))) {
  3494. String *ctypeout = Getattr(p, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
  3495. if (ctypeout)
  3496. c_param_type = ctypeout;
  3497. /* Add to local variables */
  3498. Printf(c_decl, "%s %s", c_param_type, arg);
  3499. if (!ignored_method)
  3500. Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
  3501. /* Add input marshalling code */
  3502. if ((tm = Getattr(p, "tmap:directorin"))) {
  3503. Setattr(p, "emit:directorinput", arg);
  3504. Replaceall(tm, "$input", arg);
  3505. Replaceall(tm, "$owner", "0");
  3506. if (Len(tm))
  3507. if (!ignored_method)
  3508. Printf(w->code, "%s\n", tm);
  3509. /* Add C type to callback typedef */
  3510. if (i > 0)
  3511. Printf(callback_typedef_parms, ", ");
  3512. Printf(callback_typedef_parms, "%s", c_param_type);
  3513. /* Add parameter to the intermediate class code if generating the
  3514. * intermediate's upcall code */
  3515. if ((tm = Getattr(p, "tmap:imtype"))) {
  3516. String *imtypeout = Getattr(p, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
  3517. if (imtypeout)
  3518. tm = imtypeout;
  3519. const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
  3520. String *din = Copy(Getattr(p, "tmap:csdirectorin"));
  3521. if (din) {
  3522. Replaceall(din, "$module", module_class_name);
  3523. Replaceall(din, "$imclassname", imclass_name);
  3524. substituteClassname(pt, din);
  3525. Replaceall(din, "$iminput", ln);
  3526. // pre and post attribute support
  3527. String *pre = Getattr(p, "tmap:csdirectorin:pre");
  3528. if (pre) {
  3529. substituteClassname(pt, pre);
  3530. Replaceall(pre, "$iminput", ln);
  3531. if (Len(pre_code) > 0)
  3532. Printf(pre_code, "\n");
  3533. Printv(pre_code, pre, NIL);
  3534. }
  3535. String *post = Getattr(p, "tmap:csdirectorin:post");
  3536. if (post) {
  3537. substituteClassname(pt, post);
  3538. Replaceall(post, "$iminput", ln);
  3539. if (Len(post_code) > 0)
  3540. Printf(post_code, "\n");
  3541. Printv(post_code, post, NIL);
  3542. }
  3543. String *terminator = Getattr(p, "tmap:csdirectorin:terminator");
  3544. if (terminator) {
  3545. substituteClassname(pt, terminator);
  3546. Replaceall(terminator, "$iminput", ln);
  3547. if (Len(terminator_code) > 0)
  3548. Insert(terminator_code, 0, "\n");
  3549. Insert(terminator_code, 0, terminator);
  3550. }
  3551. if (i > 0) {
  3552. Printf(delegate_parms, ", ");
  3553. Printf(proxy_method_types, ", ");
  3554. Printf(imcall_args, ", ");
  3555. }
  3556. Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
  3557. if (Cmp(din, ln)) {
  3558. Printv(imcall_args, din, NIL);
  3559. } else
  3560. Printv(imcall_args, ln, NIL);
  3561. /* Get the C# parameter type */
  3562. if ((tm = Getattr(p, "tmap:cstype"))) {
  3563. substituteClassname(pt, tm);
  3564. int flags = DOH_REPLACE_FIRST | DOH_REPLACE_ID_BEGIN | DOH_REPLACE_NOCOMMENT;
  3565. if (Replace(tm, "ref ", "", flags) || Replace(tm, "ref\t", "", flags)) {
  3566. Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm);
  3567. } else if (Replace(tm, "out ", "", flags) || Replace(tm, "out\t", "", flags)) {
  3568. Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm);
  3569. } else {
  3570. Printf(proxy_method_types, "typeof(%s)", tm);
  3571. }
  3572. } else {
  3573. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
  3574. }
  3575. } else {
  3576. Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
  3577. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3578. output_director = false;
  3579. }
  3580. } else {
  3581. Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
  3582. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3583. output_director = false;
  3584. }
  3585. p = Getattr(p, "tmap:directorin:next");
  3586. } else {
  3587. Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
  3588. "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
  3589. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3590. p = nextSibling(p);
  3591. output_director = false;
  3592. }
  3593. } else {
  3594. Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
  3595. SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3596. output_director = false;
  3597. p = nextSibling(p);
  3598. }
  3599. Delete(ln);
  3600. Delete(arg);
  3601. Delete(c_decl);
  3602. }
  3603. /* header declaration, start wrapper definition */
  3604. String *target;
  3605. SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
  3606. target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
  3607. Printf(w->def, "%s", target);
  3608. Delete(qualified_name);
  3609. Delete(target);
  3610. target = Swig_method_decl(rtype, decl, name, l, 1);
  3611. Printf(declaration, " virtual %s", target);
  3612. Delete(target);
  3613. // Add any exception specifications to the methods in the director class
  3614. if (Getattr(n, "noexcept")) {
  3615. Append(w->def, " noexcept");
  3616. Append(declaration, " noexcept");
  3617. }
  3618. ParmList *throw_parm_list = NULL;
  3619. if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
  3620. int gencomma = 0;
  3621. Append(w->def, " throw(");
  3622. Append(declaration, " throw(");
  3623. if (throw_parm_list)
  3624. Swig_typemap_attach_parms("throws", throw_parm_list, 0);
  3625. for (p = throw_parm_list; p; p = nextSibling(p)) {
  3626. if (Getattr(p, "tmap:throws")) {
  3627. if (gencomma++) {
  3628. Append(w->def, ", ");
  3629. Append(declaration, ", ");
  3630. }
  3631. Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
  3632. Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
  3633. }
  3634. }
  3635. Append(w->def, ")");
  3636. Append(declaration, ")");
  3637. }
  3638. Append(w->def, " {");
  3639. Append(declaration, ";\n");
  3640. /* Finish off the inherited upcall's definition */
  3641. Printf(callback_def, "%s)", delegate_parms);
  3642. Printf(callback_def, " {\n");
  3643. /* Emit the intermediate class's upcall to the actual class */
  3644. String *upcall = NewStringf("%s(%s)", symname, imcall_args);
  3645. if ((tm = Swig_typemap_lookup("csdirectorout", n, "", 0))) {
  3646. substituteClassname(returntype, tm);
  3647. Replaceall(tm, "$cscall", upcall);
  3648. if (!is_void)
  3649. Insert(tm, 0, "return ");
  3650. Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
  3651. // pre and post attribute support
  3652. bool is_pre_code = Len(pre_code) > 0;
  3653. bool is_post_code = Len(post_code) > 0;
  3654. bool is_terminator_code = Len(terminator_code) > 0;
  3655. if (is_pre_code && is_post_code)
  3656. Printf(callback_code, "%s\n try {\n %s;\n } finally {\n%s\n }\n", pre_code, tm, post_code);
  3657. else if (is_pre_code)
  3658. Printf(callback_code, "%s\n %s;\n", pre_code, tm);
  3659. else if (is_post_code)
  3660. Printf(callback_code, " try {\n %s;\n } finally {\n%s\n }\n", tm, post_code);
  3661. else
  3662. Printf(callback_code, " %s;\n", tm);
  3663. if (is_terminator_code)
  3664. Printv(callback_code, "\n", terminator_code, NIL);
  3665. }
  3666. Printf(callback_code, " }\n");
  3667. Delete(upcall);
  3668. if (!ignored_method) {
  3669. if (!is_void)
  3670. Printf(w->code, "jresult = (%s) ", c_ret_type);
  3671. Printf(w->code, "swig_callback%s(%s);\n", overloaded_name, jupcall_args);
  3672. if (!is_void) {
  3673. String *jresult_str = NewString("jresult");
  3674. String *result_str = NewString("c_result");
  3675. /* Copy jresult into c_result... */
  3676. if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
  3677. Replaceall(tm, "$input", jresult_str);
  3678. Replaceall(tm, "$result", result_str);
  3679. Printf(w->code, "%s\n", tm);
  3680. } else {
  3681. Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
  3682. "Unable to use return type %s used in %s::%s (skipping director method)\n",
  3683. SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
  3684. output_director = false;
  3685. }
  3686. Delete(jresult_str);
  3687. Delete(result_str);
  3688. }
  3689. /* Marshal outputs */
  3690. for (p = l; p;) {
  3691. if ((tm = Getattr(p, "tmap:directorargout"))) {
  3692. canThrow(n, "directorargout", p);
  3693. Replaceall(tm, "$result", "jresult");
  3694. Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
  3695. Printv(w->code, tm, "\n", NIL);
  3696. p = Getattr(p, "tmap:directorargout:next");
  3697. } else {
  3698. p = nextSibling(p);
  3699. }
  3700. }
  3701. /* Terminate wrapper code */
  3702. Printf(w->code, "}\n");
  3703. if (!is_void)
  3704. Printf(w->code, "return %s;", qualified_return);
  3705. }
  3706. Printf(w->code, "}");
  3707. // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
  3708. String *inline_extra_method = NewString("");
  3709. if (dirprot_mode() && !is_public(n) && !pure_virtual) {
  3710. Printv(inline_extra_method, declaration, NIL);
  3711. String *extra_method_name = NewStringf("%sSwigPublic", name);
  3712. Replaceall(inline_extra_method, name, extra_method_name);
  3713. Replaceall(inline_extra_method, ";\n", " {\n ");
  3714. if (!is_void)
  3715. Printf(inline_extra_method, "return ");
  3716. String *methodcall = Swig_method_call(super, l);
  3717. Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
  3718. Delete(methodcall);
  3719. Delete(extra_method_name);
  3720. }
  3721. /* emit the director method */
  3722. if (status == SWIG_OK && output_director) {
  3723. if (!is_void) {
  3724. Replaceall(w->code, "$null", qualified_return);
  3725. } else {
  3726. Replaceall(w->code, "$null", "");
  3727. }
  3728. if (!ignored_method)
  3729. Printv(director_delegate_callback, "\n", callback_def, callback_code, NIL);
  3730. if (!Getattr(n, "defaultargs")) {
  3731. Replaceall(w->code, "$symname", symname);
  3732. Wrapper_print(w, f_directors);
  3733. Printv(f_directors_h, declaration, NIL);
  3734. Printv(f_directors_h, inline_extra_method, NIL);
  3735. }
  3736. }
  3737. if (!ignored_method) {
  3738. /* Emit the actual upcall through */
  3739. UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name);
  3740. String *methid = Getattr(udata, "class_methodidx");
  3741. Setattr(n, "upcalldata", udata);
  3742. /*
  3743. Printf(stdout, "setting upcalldata, nodeType: %s %s::%s %p\n", nodeType(n), classname, Getattr(n, "name"), n);
  3744. */
  3745. Printf(director_callback_typedefs, " typedef %s (SWIGSTDCALL* SWIG_Callback%s_t)(", c_ret_type, methid);
  3746. Printf(director_callback_typedefs, "%s);\n", callback_typedef_parms);
  3747. Printf(director_callbacks, " SWIG_Callback%s_t swig_callback%s;\n", methid, overloaded_name);
  3748. Printf(director_delegate_definitions, " SwigDelegate%s_%s(%s);\n", classname, methid, delegate_parms);
  3749. Printf(director_delegate_instances, " private SwigDelegate%s_%s swigDelegate%s;\n", classname, methid, methid);
  3750. Printf(director_method_types, " private static global::System.Type[] swigMethodTypes%s = new global::System.Type[] { %s };\n", methid, proxy_method_types);
  3751. Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid);
  3752. }
  3753. Delete(pre_code);
  3754. Delete(post_code);
  3755. Delete(terminator_code);
  3756. Delete(qualified_return);
  3757. Delete(declaration);
  3758. Delete(callback_typedef_parms);
  3759. Delete(delegate_parms);
  3760. Delete(proxy_method_types);
  3761. Delete(callback_def);
  3762. Delete(callback_code);
  3763. Delete(dirclassname);
  3764. DelWrapper(w);
  3765. return status;
  3766. }
  3767. /* ------------------------------------------------------------
  3768. * classDirectorConstructor()
  3769. * ------------------------------------------------------------ */
  3770. int classDirectorConstructor(Node *n) {
  3771. Node *parent = parentNode(n);
  3772. String *decl = Getattr(n, "decl");
  3773. String *supername = Swig_class_name(parent);
  3774. String *dirclassname = directorClassName(parent);
  3775. String *sub = NewString("");
  3776. Parm *p;
  3777. ParmList *superparms = Getattr(n, "parms");
  3778. ParmList *parms;
  3779. int argidx = 0;
  3780. /* Assign arguments to superclass's parameters, if not already done */
  3781. for (p = superparms; p; p = nextSibling(p)) {
  3782. String *pname = Getattr(p, "name");
  3783. if (!pname) {
  3784. pname = NewStringf("arg%d", argidx++);
  3785. Setattr(p, "name", pname);
  3786. }
  3787. }
  3788. // TODO: Is this copy needed?
  3789. parms = CopyParmList(superparms);
  3790. if (!Getattr(n, "defaultargs")) {
  3791. /* constructor */
  3792. {
  3793. String *basetype = Getattr(parent, "classtype");
  3794. String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
  3795. String *call = Swig_csuperclass_call(0, basetype, superparms);
  3796. Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
  3797. Printf(f_directors, " swig_init_callbacks();\n");
  3798. Printf(f_directors, "}\n\n");
  3799. Delete(target);
  3800. Delete(call);
  3801. }
  3802. /* constructor header */
  3803. {
  3804. String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
  3805. Printf(f_directors_h, " %s;\n", target);
  3806. Delete(target);
  3807. }
  3808. }
  3809. Delete(sub);
  3810. Delete(supername);
  3811. Delete(parms);
  3812. Delete(dirclassname);
  3813. return Language::classDirectorConstructor(n);
  3814. }
  3815. /* ------------------------------------------------------------
  3816. * classDirectorDefaultConstructor()
  3817. * ------------------------------------------------------------ */
  3818. int classDirectorDefaultConstructor(Node *n) {
  3819. String *dirclassname = directorClassName(n);
  3820. String *classtype = SwigType_namestr(Getattr(n, "name"));
  3821. Wrapper *w = NewWrapper();
  3822. Printf(w->def, "%s::%s() : %s {", dirclassname, dirclassname, Getattr(n, "director:ctor"));
  3823. Printf(w->code, "}\n");
  3824. Wrapper_print(w, f_directors);
  3825. Printf(f_directors_h, " %s();\n", dirclassname);
  3826. DelWrapper(w);
  3827. Delete(classtype);
  3828. Delete(dirclassname);
  3829. return Language::classDirectorDefaultConstructor(n);
  3830. }
  3831. /* ------------------------------------------------------------
  3832. * classDirectorInit()
  3833. * ------------------------------------------------------------ */
  3834. int classDirectorInit(Node *n) {
  3835. Delete(none_comparison);
  3836. none_comparison = NewString(""); // not used
  3837. Delete(director_ctor_code);
  3838. director_ctor_code = NewString("$director_new");
  3839. directorDeclaration(n);
  3840. Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
  3841. Printf(f_directors_h, "\npublic:\n");
  3842. /* Keep track of the director methods for this class */
  3843. first_class_dmethod = curr_class_dmethod = n_dmethods;
  3844. director_callback_typedefs = NewString("");
  3845. director_callbacks = NewString("");
  3846. director_delegate_callback = NewString("");
  3847. director_delegate_definitions = NewString("");
  3848. director_delegate_instances = NewString("");
  3849. director_method_types = NewString("");
  3850. director_connect_parms = NewString("");
  3851. return Language::classDirectorInit(n);
  3852. }
  3853. int classDeclaration(Node *n) {
  3854. String *old_director_callback_typedefs = director_callback_typedefs;
  3855. String *old_director_callbacks = director_callbacks;
  3856. String *old_director_delegate_callback = director_delegate_callback;
  3857. String *old_director_delegate_definitions = director_delegate_definitions;
  3858. String *old_director_delegate_instances = director_delegate_instances;
  3859. String *old_director_method_types = director_method_types;
  3860. String *old_director_connect_parms = director_connect_parms;
  3861. int ret = Language::classDeclaration(n);
  3862. // these variables are deleted in emitProxyClassDefAndCPPCasts, hence no Delete here
  3863. director_callback_typedefs = old_director_callback_typedefs;
  3864. director_callbacks = old_director_callbacks;
  3865. director_delegate_callback = old_director_delegate_callback;
  3866. director_delegate_definitions = old_director_delegate_definitions;
  3867. director_delegate_instances = old_director_delegate_instances;
  3868. director_method_types = old_director_method_types;
  3869. director_connect_parms = old_director_connect_parms;
  3870. return ret;
  3871. }
  3872. /* ----------------------------------------------------------------------
  3873. * classDirectorDestructor()
  3874. * ---------------------------------------------------------------------- */
  3875. int classDirectorDestructor(Node *n) {
  3876. Node *current_class = getCurrentClass();
  3877. String *dirclassname = directorClassName(current_class);
  3878. Wrapper *w = NewWrapper();
  3879. if (Getattr(n, "noexcept")) {
  3880. Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
  3881. Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
  3882. } else if (Getattr(n, "throw")) {
  3883. Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
  3884. Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
  3885. } else {
  3886. Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
  3887. Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);
  3888. }
  3889. Printv(w->code, "}\n", NIL);
  3890. Wrapper_print(w, f_directors);
  3891. DelWrapper(w);
  3892. Delete(dirclassname);
  3893. return SWIG_OK;
  3894. }
  3895. /* ------------------------------------------------------------
  3896. * classDirectorEnd()
  3897. * ------------------------------------------------------------ */
  3898. int classDirectorEnd(Node *n) {
  3899. int i;
  3900. String *dirclassname = directorClassName(n);
  3901. Wrapper *w = NewWrapper();
  3902. if (Len(director_callback_typedefs) > 0) {
  3903. Printf(f_directors_h, "\n%s", director_callback_typedefs);
  3904. }
  3905. Printf(f_directors_h, " void swig_connect_director(");
  3906. Printf(w->def, "void %s::swig_connect_director(", dirclassname);
  3907. for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  3908. UpcallData *udata = Getitem(dmethods_seq, i);
  3909. String *methid = Getattr(udata, "class_methodidx");
  3910. String *overname = Getattr(udata, "overname");
  3911. Printf(f_directors_h, "SWIG_Callback%s_t callback%s", methid, overname);
  3912. Printf(w->def, "SWIG_Callback%s_t callback%s", methid, overname);
  3913. Printf(w->code, "swig_callback%s = callback%s;\n", overname, overname);
  3914. if (i != curr_class_dmethod - 1) {
  3915. Printf(f_directors_h, ", ");
  3916. Printf(w->def, ", ");
  3917. }
  3918. }
  3919. Printf(f_directors_h, ");\n");
  3920. Printf(w->def, ") {");
  3921. if (Len(director_callbacks) > 0) {
  3922. Printf(f_directors_h, "\nprivate:\n%s", director_callbacks);
  3923. }
  3924. Printf(f_directors_h, " void swig_init_callbacks();\n");
  3925. Printf(f_directors_h, "};\n\n");
  3926. Printf(w->code, "}\n\n");
  3927. Printf(w->code, "void %s::swig_init_callbacks() {\n", dirclassname);
  3928. for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  3929. UpcallData *udata = Getitem(dmethods_seq, i);
  3930. String *overname = Getattr(udata, "overname");
  3931. Printf(w->code, "swig_callback%s = 0;\n", overname);
  3932. }
  3933. Printf(w->code, "}");
  3934. Wrapper_print(w, f_directors);
  3935. DelWrapper(w);
  3936. Delete(dirclassname);
  3937. return Language::classDirectorEnd(n);
  3938. }
  3939. /* --------------------------------------------------------------------
  3940. * classDirectorDisown()
  3941. * ------------------------------------------------------------------*/
  3942. virtual int classDirectorDisown(Node *n) {
  3943. (void) n;
  3944. return SWIG_OK;
  3945. }
  3946. /*----------------------------------------------------------------------
  3947. * extraDirectorProtectedCPPMethodsRequired()
  3948. *--------------------------------------------------------------------*/
  3949. bool extraDirectorProtectedCPPMethodsRequired() const {
  3950. return false;
  3951. }
  3952. /*----------------------------------------------------------------------
  3953. * directorDeclaration()
  3954. *
  3955. * Generate the director class's declaration
  3956. * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
  3957. *--------------------------------------------------------------------*/
  3958. void directorDeclaration(Node *n) {
  3959. String *base = Getattr(n, "classtype");
  3960. String *class_ctor = NewString("Swig::Director()");
  3961. String *dirclassname = directorClassName(n);
  3962. String *declaration = Swig_class_declaration(n, dirclassname);
  3963. Printf(declaration, " : public %s, public Swig::Director", base);
  3964. // Stash stuff for later.
  3965. Setattr(n, "director:decl", declaration);
  3966. Setattr(n, "director:ctor", class_ctor);
  3967. Delete(dirclassname);
  3968. }
  3969. /*----------------------------------------------------------------------
  3970. * nestedClassesSupport()
  3971. *--------------------------------------------------------------------*/
  3972. NestedClassSupport nestedClassesSupport() const {
  3973. return NCS_Full;
  3974. }
  3975. }; /* class CSHARP */
  3976. /* -----------------------------------------------------------------------------
  3977. * swig_csharp() - Instantiate module
  3978. * ----------------------------------------------------------------------------- */
  3979. static Language *new_swig_csharp() {
  3980. return new CSHARP();
  3981. }
  3982. extern "C" Language *swig_csharp(void) {
  3983. return new_swig_csharp();
  3984. }
  3985. /* -----------------------------------------------------------------------------
  3986. * Static member variables
  3987. * ----------------------------------------------------------------------------- */
  3988. const char *CSHARP::usage = "\
  3989. C# Options (available with -csharp)\n\
  3990. -dllimport <dl> - Override DllImport attribute name to <dl>\n\
  3991. -namespace <nm> - Generate wrappers into C# namespace <nm>\n\
  3992. -noproxy - Generate the low-level functional interface instead\n\
  3993. of proxy classes\n\
  3994. -oldvarnames - Old intermediary method names for variable wrappers\n\
  3995. -outfile <file> - Write all C# into a single <file> located in the output directory\n\
  3996. \n";