Skip to content

Commit 3108f9e

Browse files
committed
Merge branch 'typemap-colon'
2 parents 34c219b + 1571d91 commit 3108f9e

File tree

4 files changed

+75
-16
lines changed

4 files changed

+75
-16
lines changed

Doc/Manual/Typemaps.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,6 +2457,40 @@ <H4><a name="Typemaps_special_macro_typemap">14.4.4.2 $typemap(method, typepatte
24572457
</pre>
24582458
</div>
24592459

2460+
<H4><a name="Typemaps_special_macro_typemap_attribute">14.4.4.3 $typemap(method:attribute, typepattern)</a></H4>
2461+
2462+
<p>
2463+
An enhanced version of <tt>$typemap</tt> provides access to typemap attributes by
2464+
appending a colon and the attribute name after the attribute name. In the example below,
2465+
"cstype" is the typemap method and "out" is the typemap attribute.
2466+
<p>
2467+
2468+
<div class="code">
2469+
<pre>
2470+
%typemap(cstype, out="object") XClass "XClass"
2471+
%typemap(cscode) BarClass %{
2472+
$typemap(cstype:out, XClass) bar()
2473+
{
2474+
return null;
2475+
}
2476+
</pre>
2477+
</div>
2478+
<p>
2479+
which expands to
2480+
</p>
2481+
<div class="code">
2482+
<pre>
2483+
object bar()
2484+
{
2485+
return null;
2486+
}
2487+
</pre>
2488+
</div>
2489+
2490+
<p>
2491+
<b>Compatibility note: </b> Support for typemap attributes in <tt>$typemap</tt>
2492+
was introduced in SWIG-4.1.0.
2493+
</p>
24602494

24612495
<H3><a name="Typemaps_special_variable_attributes">14.4.5 Special variables and typemap attributes</a></H3>
24622496

Examples/test-suite/python/special_variable_macros_runme.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import special_variable_macros
22

3+
cvar = special_variable_macros.cvar
34
name = special_variable_macros.Name()
45
if special_variable_macros.testFred(name) != "none":
56
raise "test failed"
7+
if cvar.accessed_examplekw != 0:
8+
raise "Precondition failed"
69
if special_variable_macros.testJack(name) != "$specialname":
710
raise "test failed"
11+
if cvar.accessed_examplekw != 1:
12+
raise "Postcondition failed"
813
if special_variable_macros.testJill(name) != "jilly":
914
raise "test failed"
1015
if special_variable_macros.testMary(name) != "SWIGTYPE_p_NameWrap":

Examples/test-suite/special_variable_macros.i

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,13 @@ struct NameWrap {
3939
private:
4040
Name name;
4141
};
42+
43+
// Global variable for testing whether examplekw was touched
44+
int accessed_examplekw = 0;
4245
%}
4346

4447
// check $1 and $input get expanded properly when used from $typemap()
45-
%typemap(in) Name *GENERIC ($*1_type temp)
48+
%typemap(in, examplekw="accessed_examplekw=1;") Name *GENERIC ($*1_type temp)
4649
%{
4750
/*%typemap(in) Name *GENERIC start */
4851
temp = Name("$specialname");
@@ -80,6 +83,7 @@ static const char *nameDescriptor = "$descriptor(Name)";
8083
%typemap(in) Name *jack {
8184
// %typemap(in) Name *jack start
8285
$typemap(in, Name *GENERIC)
86+
$typemap(in:examplekw, Name *GENERIC)
8387
// %typemap(in) Name *jack end
8488
}
8589

Source/Swig/typemap.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,12 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) {
511511
if (sm) {
512512
/* Got a typemap. Need to only merge attributes for methods that match our signature */
513513
Iterator ki;
514+
Hash *deferred_add;
514515
match = 1;
516+
517+
/* Since typemap_register can modify the `sm` hash, we *cannot* call typemap_register while iterating over sm.
518+
* Create a temporary hash of typemaps to add immediately after. */
519+
deferred_add = NewHash();
515520
for (ki = First(sm); ki.key; ki = Next(ki)) {
516521
/* Check for a signature match with the source signature */
517522
if ((count_args(ki.key) == narg) && (Strstr(ki.key, ssig))) {
@@ -521,34 +526,36 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) {
521526
Replace(nkey, ssig, dsig, DOH_REPLACE_ANY);
522527

523528
/* Make sure the typemap doesn't already exist in the target map */
524-
525529
oldm = Getattr(tm, nkey);
526530
if (!oldm || (!Getattr(tm, "code"))) {
527531
String *code;
528-
ParmList *locals;
529-
ParmList *kwargs;
530532
Hash *sm1 = ki.item;
531533

532534
code = Getattr(sm1, "code");
533-
locals = Getattr(sm1, "locals");
534-
kwargs = Getattr(sm1, "kwargs");
535535
if (code) {
536-
String *src_str = ParmList_str_multibrackets(src);
537-
String *dest_str = ParmList_str_multibrackets(dest);
538-
String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str);
539-
540536
Replace(nkey, dsig, "", DOH_REPLACE_ANY);
541537
Replace(nkey, "tmap:", "", DOH_REPLACE_ANY);
542-
typemap_register(nkey, dest, code, locals, kwargs, source_directive);
543-
544-
Delete(source_directive);
545-
Delete(dest_str);
546-
Delete(src_str);
538+
Setattr(deferred_add, nkey, sm1);
547539
}
548540
}
549541
Delete(nkey);
550542
}
551543
}
544+
545+
/* After assembling the key/item pairs, add the resulting typemaps */
546+
for (ki = First(deferred_add); ki.key; ki = Next(ki)) {
547+
Hash *sm1 = ki.item;
548+
String *src_str = ParmList_str_multibrackets(src);
549+
String *dest_str = ParmList_str_multibrackets(dest);
550+
String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str);
551+
552+
typemap_register(ki.key, dest, Getattr(sm1, "code"), Getattr(sm1, "locals"), Getattr(sm1, "kwargs"), source_directive);
553+
554+
Delete(source_directive);
555+
Delete(dest_str);
556+
Delete(src_str);
557+
}
558+
Delete(deferred_add);
552559
}
553560
Delete(ssig);
554561
Delete(dsig);
@@ -2084,14 +2091,23 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper
20842091
Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
20852092
#endif
20862093
if (already_substituting < 10) {
2094+
char* found_colon;
20872095
already_substituting++;
20882096
if ((in_typemap_search_multi == 0) && typemap_search_debug) {
20892097
String *dtypemap = NewString(dollar_typemap);
20902098
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
20912099
Printf(stdout, " Containing: %s\n", dtypemap);
20922100
Delete(dtypemap);
20932101
}
2094-
Swig_typemap_attach_parms(tmap_method, to_match_parms, f);
2102+
found_colon = Strchr(tmap_method, ':');
2103+
if (found_colon) {
2104+
/* Substitute from a keyword argument to a typemap. Avoid emitting local variables from the attached typemap by passing NULL for the file. */
2105+
String *temp_tmap_method = NewStringWithSize(Char(tmap_method), found_colon - Char(tmap_method));
2106+
Swig_typemap_attach_parms(temp_tmap_method, to_match_parms, NULL);
2107+
Delete(temp_tmap_method);
2108+
} else {
2109+
Swig_typemap_attach_parms(tmap_method, to_match_parms, f);
2110+
}
20952111
already_substituting--;
20962112

20972113
/* Look for the typemap code */

0 commit comments

Comments
 (0)