1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>SWIG and C as the target language</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body bgcolor="#FFFFFF">
<H1><a name="C">38 SWIG and C as the target language</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#C_overview">Overview</a>
<ul>
<li><a href="#C_shortcomings">Known C++ Shortcomings in Generated C API</a>
</ul>
<li><a href="#C_preliminaries">Preliminaries</a>
<ul>
<li><a href="#C_running_swig">Running SWIG</a>
<li><a href="#C_commandline">Command line options</a>
<li><a href="#C_dynamic">Compiling a dynamic module</a>
<li><a href="#C_using_module">Using the generated module</a>
</ul>
<li><a href="#C_basic_c_wrapping">Basic C wrapping</a>
<ul>
<li><a href="#C_functions">Functions</a>
<li><a href="#C_variables">Variables</a>
</ul>
<li><a href="#C_basic_cpp_wrapping">Basic C++ wrapping</a>
<ul>
<li><a href="#C_enums">Enums</a>
<li><a href="#C_classes">Classes</a>
</ul>
<li><a href="#C_developer">Backend Developer Documentation</a>
<li><a href="#C_typemaps">Typemaps</a>
<ul>
<li><a href="#C_typemaps_walkthrough">C Typemaps, a Code Generation Walkthrough</a>
<ul>
<li><a href="#C_walkthrough_interface">The Interface</a>
<li><a href="#C_walkthrough_wrapper">The Wrapper</a>
<li><a href="#C_walkthrough_proxy">The Proxy</a>
</ul>
</ul>
<li><a href="#C_exceptions">Exception handling</a>
<li><a href="#C_cxx_wrappers">C++ Wrappers</a>
<ul>
<li><a href="#C_additional_possibilities">Additional customization possibilities</a>
<li><a href="#C_exception_handling">Exception handling</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support for creating ISO C wrappers. This module has a special purpose and thus is different from most other modules.
</p>
<p>
<b>NOTE:</b> this module is still under development.
</p>
<H2><a name="C_overview">38.1 Overview</a></H2>
<p>
SWIG is normally used to provide access to C or C++ libraries from target languages such as scripting languages or languages running on a virtual machine.
SWIG performs analysis of the input C/C++ library header files from which it generates further code. For most target languages this code consists of two layers; namely an intermediary C code layer and a set of language specific proxy classes and functions on top of the C code layer.
We could also think of C as just another target language supported by SWIG.
The aim then is to generate a pure ISO C interface to the input C or C++ library and hence the C target language module.
</p>
<p>
With wrapper interfaces generated by SWIG, it is easy to use the functionality of C++ libraries inside application code written in C. This module may also be useful to generate custom APIs for a library, to suit particular needs, e.g. to supply function calls with error checking or to implement a "design by contract".
</p>
<p>
Flattening C++ language constructs into a set of C-style functions obviously comes with many limitations and inconveniences, but this module is actually also capable of generating C++ wrappers defined completely inline using the C functions, thus wrapping the original C++ library API in another, similar C++ API. Contrary to the natural initial reaction, this is far from being completely pointless, as wrapping C++ API in this way avoids all problems due to C++ ABI issues, e.g. it is now possible to use the original C++ API using a different C++ compiler, or a different version of the same compiler, or even the same compiler, but with different compilation options affecting the ABI. The C++ wrapper API is not identical to the original one, but strives to be as close to it as possible.
</p>
<H3><a name="C_shortcomings">38.1.1 Known C++ Shortcomings in Generated C API</a></H3>
<ul>
<li>Enums with a context like class or namespace are broken</li>
<li>Global variables are not supported</li>
<li>Qualifiers are stripped</li>
<li>Vararg functions are not supported.</li>
</ul>
<H2><a name="C_preliminaries">38.2 Preliminaries</a></H2>
<H3><a name="C_running_swig">38.2.1 Running SWIG</a></H3>
<p>
Consider the following simple example. Suppose we have an interface file like:
</p>
<div class="code">
<pre>
/* File: example.i */
%module test
%{
#include "stuff.h"
%}
int fact(int n);
</pre>
</div>
<p>
To build a C module (C as the target language), run SWIG using the <tt>-c</tt> option :</p>
<div class="shell"><pre>
$ swig -c example.i
</pre></div>
<p>
The above assumes C as the input language. If the input language is C++ add the <tt>-c++</tt> option:
</p>
<div class="shell"><pre>
$ swig -c++ -c example.i
</pre></div>
<p>
Note that <tt>-c</tt> is the option specifying the <b>target</b> language and <tt>-c++</tt> controls what the <b>input</b> language is.
</p>
<p>
This will generate an <tt>example_wrap.c</tt> file or, in the latter case, <tt>example_wrap.cxx</tt> file, along with <tt>example_wrap.h</tt> (the same extension is used in both C and C++ cases for the last one). The names of the files are derived from the name of the input file by default, but can be changed using the <tt>-o</tt> and <tt>-oh</tt> options common to all language modules.
</p>
<p>
The <tt>xxx_wrap.c</tt> file contains the wrapper functions, which perform the main functionality of SWIG: each of the wrappers translates the input arguments from C to C++, makes calls to the original functions and marshals C++ output back to C data. The <tt>xxx_wrap.h</tt> header file contains the declarations of these functions as well as global variables.
</p>
<H3><a name="C_commandline">38.2.2 Command line options</a></H3>
<p>
The following table list the additional command line options available for the C module. They can also be seen by using:
</p>
<div class="shell"><pre>
$ swig -c -help
</pre></div>
<table summary="C specific options">
<tr>
<th>C specific options</th>
</tr>
<tr>
<td>-namespace <nspace></td>
<td>Generate wrappers with the prefix based on the provided namespace, e.g. if the option value is <tt>outer::inner</tt>, the prefix <tt>outer_inner_</tt> will be used. Notice that this is different from using SWIG <tt>nspace</tt> feature, as it applies the prefix to all the symbols, regardless of the namespace they were actually declared in. Notably, this provides a way to export instantiations of templates defined in the <tt>std</tt> namespace, such as <tt>std::vector</tt>, using a custom prefix rather than <tt>std_</tt>.</td>
</tr>
<tr>
<td>-nocxx</td>
<td>Don't generate C++ wrappers, even when the <tt>-c++</tt> option is used. See <a href="#C_cxx_wrappers">C++ Wrappers</a> section for more details.</td>
</tr>
<tr>
<td>-noexcept</td>
<td>generate wrappers with no support for exception handling; see <a href="#C_exceptions">Exceptions</a> chapter for more details </td>
</tr>
</table>
<H3><a name="C_dynamic">38.2.3 Compiling a dynamic module</a></H3>
<p>
The next step is to build a dynamically loadable module, which we can link to our application. For example, to do this using the <tt>gcc</tt> compiler (Linux, MinGW, etc.):
</p>
<div class="shell"><pre>
$ swig -c example.i
$ gcc -fPIC -c example_wrap.c
$ gcc -shared example_wrap.o -o libexample.so
</pre></div>
<p>
Or, for C++ input:
</p>
<div class="shell"><pre>
$ swig -c++ -c example.i
$ g++ -fPIC -c example_wrap.cxx
$ g++ -shared example_wrap.o -o libexample.so
</pre></div>
<p>
Now the shared library module is ready to use. Note that the name of the generated module is important: is should be prefixed with <tt>lib</tt> on Unix, and have the specific extension, like <tt>.dll</tt> for Windows or <tt>.so</tt> for Unix systems.
</p>
<H3><a name="C_using_module">38.2.4 Using the generated module</a></H3>
<p>
The simplest way to use the generated shared module is to link it to the application code during the compilation stage. The process is usually similar to this:
</p>
<div class="shell"><pre>
$ gcc runme.c -L. -lexample -o runme
</pre></div>
<p>
This will compile the application code (<tt>runme.c</tt>) and link it against the generated shared module. Following the <tt>-L</tt> option is the path to the directory containing the shared module. The output executable is ready to use. The last thing to do is to supply to the operating system the information of location of our module. This is system dependant, for instance Unix systems look for shared modules in certain directories, like <tt>/usr/lib</tt>, and additionally we can set the environment variable <tt>LD_LIBRARY_PATH</tt> (Unix) or <tt>PATH</tt> (Windows) for other directories.
</p>
<H2><a name="C_basic_c_wrapping">38.3 Basic C wrapping</a></H2>
<p>
Wrapping C functions and variables is obviously performed in a straightforward way. There is no need to perform type conversions, and all language constructs can be preserved in their original form. However, SWIG allows you to enhance the code with some additional elements, for instance using a <tt>check</tt> typemap or <tt>%extend</tt> directive.
</p>
<p>
It is also possible to output arbitrary additional code into the generated header by using the <tt>%insert</tt> directive with <tt>cheader</tt> section, e.g.
</p>
<div class="code"><pre>
%insert("cheader") %{
#include "another.h"
%}
</pre></div>
<H3><a name="C_functions">38.3.1 Functions</a></H3>
<p>
For each C function declared in the interface file a wrapper function with a prefix, required to make its name different from the original one, is created. The prefix for the global functions is <tt>module_</tt>, i.e. the name of the SWIG module followed by underscore, by default. If <tt>-namespace</tt> option is used, the prefix corresponding to the given fixed namespace is used instead. If <tt>nspace</tt> feature is used, the prefix corresponding to the namespace in which the function is defined is used -- note that, unlike with <tt>-namespace</tt> option, this prefix can be different for different functions. The wrapper function performs a call to the original function, and returns its result.
</p>
<p>
For example, for function declaration in the module <tt>mymath</tt>:
</p>
<div class="targetlang"><pre>
int gcd(int x, int y);
</pre></div>
<p>
The output is simply:
</p>
<div class="targetlang"><pre>
int mymath_gcd(int arg1, int arg2) {
int result;
result = gcd(arg1,arg2);
return result;
}
</pre></div>
<p>
Now one might think, what's the use of creating such functions in C? The answer is, you can apply special rules to the generated code. Take for example constraint checking. You can write a "check" typemap in your interface file:
</p>
<div class="code"><pre>
%typemap(check) int POSITIVE {
if ($1 <= 0)
fprintf(stderr, "Expected positive value for parameter $1 in $name.\n");
}
int gcd(int POSITIVE, int POSITIVE);
</pre></div>
<p>
And now the generated result looks like:
</p>
<div class="targetlang"><pre>
int _wrap_gcd(int arg1, int arg2) {
int result;
{
if (arg1 <= 0)
fprintf(stderr, "Expected positive value for parameter arg1 in gcd.\n");
}
{
if (arg2 <= 0)
fprintf(stderr, "Expected positive value for parameter arg2 in gcd.\n");
}
result = gcd(arg1,arg2);
return result;
}
</pre></div>
<p>
This time calling <tt>gcd</tt> with negative value argument will trigger an error message. This can save you time writing all the constraint checking code by hand.
</p>
<H3><a name="C_variables">38.3.2 Variables</a></H3>
<p>
Wrapping variables comes also without any special issues. All global variables are directly accessible from application code. There is a difference in the semantics of <tt>struct</tt> definition in C and C++. When handling C <tt>struct</tt>, SWIG simply rewrites its declaration. In C++ <tt>struct</tt> is handled as class declaration.
</p>
<p>
You can still apply some of the SWIG features when handling structs, e.g. <tt>%extend</tt> directive. Suppose, you have a C struct declaration:
</p>
<div class="targetlang"><pre>
typedef struct {
int x;
char *str;
} my_struct;
</pre></div>
<p>
You can redefine it to have an additional fields, like:
</p>
<div class="code"><pre>
%extend my_struct {
double d;
};
</pre></div>
<p>
In application code:
</p>
<div class="targetlang"><pre>
struct my_struct ms;
ms.x = 123;
ms.d = 123.123;
</pre></div>
<H2><a name="C_basic_cpp_wrapping">38.4 Basic C++ wrapping</a></H2>
<p>
The main reason of having the C module in SWIG is to be able to access C++ from C. In this chapter we will take a look at the rules of wrapping elements of the C++ language.
</p>
<p>
By default, SWIG attempts to build a natural C interface to your C/C++ code.
</p>
<table BORDER summary="Generated C representation of C++">
<tr>
<th>C++ Type</th>
<th>SWIG C Translation</th>
</tr>
<tr>
<td>Class <tt>Example</tt></td>
<td>Empty structure <tt>Example</tt></td>
</tr>
<tr>
<td>Public, mutable member variable <tt>Foo Example::foo</tt></td>
<td><div class="targetlang"><pre>
Example_foo_get(Example *e);
Example_foo_set(Example *e, Foo *f);
</pre></div></td>
</tr>
<tr>
<td>Public, immutable member variable <tt>Foo Example::bar</tt></td>
<td><div class="targetlang"><pre>
Example_foo_get(Example *e);
</pre></div></td>
</tr>
</table>
<p>
This section briefly covers the essential aspects of this wrapping.
</p>
<H3><a name="C_enums">38.4.1 Enums</a></H3>
<p>
C enums and unscoped C++ enums are simply copied to the generated code and both the enum itself and its elements keep the same name as in the original code unless <tt>-namespace</tt> option is used or <tt>nspace</tt> feature is enabled, in which case the prefix corresponding to the specified namespace is used.
</p>
<p>
For scoped C++11 enums, the enum name itself is used as an additional prefix.
</p>
<H3><a name="C_classes">38.4.2 Classes</a></H3>
<p>
Consider the following example. We have a C++ class, and want to use it from C code.
</p>
<div class="targetlang"><pre>
class Circle {
public:
double radius;
Circle(double r) : radius(r) { };
double area(void);
};
</pre></div>
<p>
What we need to do is to create an object of the class, manipulate it, and finally, destroy it. SWIG generates C functions for this purpose each time a class declaration is encountered in the interface file.
</p>
<p>
The first two generated functions are used to create and destroy instances of class <tt>Circle</tt>. Such instances are represented on the C side as pointers to special structs, called <tt>SwigObj</tt>. They are all "renamed" (via typedef) to the original class names, so that you can use the object instances on the C side using pointers like:
</p>
<div class="targetlang"><pre>
Circle *circle;
</pre></div>
<p>
The generated functions make calls to class' constructors and destructors, respectively. They also do all the necessary things required by the SWIG object management system in C.
</p>
<div class="targetlang"><pre>
Circle * Circle_new(double r);
void Circle_delete(Circle * self);
</pre></div>
<p>
The class <tt>Circle</tt> has a public variable called <tt>radius</tt>. SWIG generates a pair of setters and getters for each such variable:
</p>
<div class="targetlang"><pre>
void Circle_radius_set(Circle * self, double radius);
double Circle_radius_get(Circle * self);
</pre></div>
<p>
For each public method, an appropriate function is generated:
</p>
<div class="targetlang"><pre>
double Circle_area(Circle * self);
</pre></div>
<p>
You can see that in order to use the generated object we need to provide a pointer to the object instance (struct <tt>Circle</tt> in this case) as the first function argument. In fact, this struct is basically wrapping pointer to the "real" C++ object.
</p>
<p>
Our application code could look like this:
</p>
<div class="targetlang"><pre>
Circle *c = Circle_new(1.5);
printf("radius: %f\narea: %f\n", Circle_radius_get(c), Circle_area(c));
Circle_delete(c);
</pre></div>
<p>
After running this we'll get:
</p>
<div class="shell"><pre>
radius: 1.500000
area: 7.068583
</pre></div>
<H2><a name="C_developer">38.5 Backend Developer Documentation</a></H2>
<H2><a name="C_typemaps">38.6 Typemaps</a></H2>
<table BORDER summary="C Backend Typemaps">
<tr>
<th>Typemap</th>
<th>Used for</th>
</tr>
<tr>
<td><tt>ctype</tt></td>
<td>Provides types used for the C API and<br>
Typecasts wrapper functions return values in proxy functions
<div class="targetlang"><pre>
MyClass *MyClass_new(void) {
return (MyClass *)MyClass_new();
}
</pre></div>
</td>
</tr>
<tr>
<td><tt>in</tt></td>
<td>Mapping of wrapper functions parameters to local C++ variables
<div class="targetlang"><pre>
SwigObj* MyClass_do(SwigObj *carg1) {
SomeCPPClass *arg1 = 0;
if (carg1)
arg1 = (SomeCPPClass*)carg1->obj
else
arg1 = 0;
}
</pre></div>
</td>
</tr>
<tr>
<td><tt>out</tt></td>
<td>Assigns wrapped function's return value to a dedicated return variable, packaging it into SwigObj if necessary</td>
</tr>
<tr>
<td><tt>cppouttype</tt></td>
<td>Type of the result variable used for the return value if the wrapped function is a C++ function
</td>
</tr>
<tr>
<td><tt>cxxintype</tt></td>
<td>Defines the type for the parameters of C++ wrapper functions corresponding to this type. By default is the same as <tt>ctype</tt>, but may sometimes be different to make the functions more convenient to use. For example, <tt>ctype</tt> for <tt>std::string</tt> is <tt>const char*</tt>, but <tt>cxxintype</tt> typemap for it is <tt>std::string const&</tt>, i.e. even though the C++ string passed as a raw pointer via C API, the C++ wrapper still accepts a C++ string. If this typemap is defined, <tt>cxxin</tt> should normally be defined as well. If it is not defined, <tt>ctype</tt> is used.
</td>
</tr>
<tr>
<td><tt>cxxouttype</tt></td>
<td>Similar to <tt>cxxintype</tt>, but is used for the function return values and together with <tt>cxxout</tt> typemap. Also defaults to <tt>ctype</tt> if not defined.
</td>
</tr>
<tr>
<td><tt>cxxin</tt></td>
<td>Defines how to transform <tt>cxxintype</tt> value to <tt>ctype</tt>
</td>
</tr>
<tr>
<td><tt>cxxout</tt></td>
<td>Defines how to transform <tt>ctype</tt> value returned by a function to <tt>cxxouttype</tt>
</td>
</tr>
<tr>
<td><tt>cxxcode</tt></td>
<td>May contain arbitrary code that will be injected in the declaration of the C++ wrapper class corresponding to the given type. Ignored for non-class types. The special variable <tt>$cxxclassname</tt> is replaced with the name of the class inside this typemap expansion and <tt>$cclassptrname</tt> is replaced with the name of the pointer type used to represent the class in C wrapper functions.
</td>
</tr>
</table>
<H3><a name="C_typemaps_walkthrough">38.6.1 C Typemaps, a Code Generation Walkthrough</a></H3>
<p>
To get a better idea of which typemap is used for which generated code, have a look at the following 'walk through'.
</p>
<p>
Let's assume we have the following C++ interface file, we'd like to generate code for:
</p>
<H4><a name="C_walkthrough_interface">38.6.1.1 The Interface</a></H4>
<div class="code"><pre>
%module example
%inline
%{
class SomeClass{};
template <typename T> class SomeTemplateClass{};
SomeClass someFunction(SomeTemplateClass<int> &someParameter, int simpleInt);
%}
%template (SomeIntTemplateClass) SomeTemplateClass<int>;
</pre></div>
<p>
What we would like to generate as a C interface of this function would be something like this:
</p>
<div class="targetlang"><pre>
// wrapper header file
typedef struct SwigObj_SomeClass SomeClass;
SomeClass * SomeClass_new();
void SomeClass_delete(SomeClass * carg1);
SomeClass* someFunction(SomeIntTemplateClass* carg1, int carg2);
typedef struct SwigObj_SomeIntTemplateClass SomeIntTemplateClass;
SomeIntTemplateClass * SomeIntTemplateClass_new();
void SomeIntTemplateClass_delete(SomeIntTemplateClass * carg1);
</pre></div>
<H4><a name="C_walkthrough_wrapper">38.6.1.2 The Wrapper</a></H4>
<p>
We'll examine the generation of the wrapper function first.
</p>
<div class="targetlang"><pre>
SWIGEXPORTC SwigObj * module_someFunction(SwigObj * carg1, int carg2) {
SomeClass * cppresult;
SomeTemplateClass< int > *arg1 = 0 ;
int arg2 ;
SwigObj * result;
{
if (carg1)
arg1 = (SomeTemplateClass< int > *) carg1->obj;
else
arg1 = (SomeTemplateClass< int > *) 0;
}
arg2 = (int) carg2;
{
const SomeClass &_result_ref = someFunction(*arg1,arg2);cppresult = (SomeClass*) &_result_ref;
}
{
result = SWIG_create_object(cppresult, SWIG_STR(SomeClass));
}
return result;
}
</pre></div>
<p>
It might be helpful to think of the way function calls are generated as a composition of building blocks.
A typical wrapper will be composited with these [optional] blocks:
</p>
<ol>
<li>Prototype</li>
<li>C return value variable</li>
<li>Local variables equal to the called C++ function's parameters</li>
<li>[C++ return value variable]</li>
<li>Assignment (extraction) of wrapper parameters to local parameter copies</li>
<li>[Contract (e.g. constraints) checking]</li>
<li> C++ function call</li>
<li>[Exception handling]</li>
<li>[Assignment to C++ return value]</li>
<li>Assignment to C return value</li>
</ol>
<p>
Let's go through it step by step and start with the wrapper prototype
</p>
<div class="targetlang"><pre>
ctype ctype ctype
--------- --------- ---
SwigObj * module_someFunction(SwigObj * carg1, int carg2);
</pre></div>
<p>
As first unit of the wrapper code, a variable to hold the return value of the function is emitted to the wrapper's body
</p>
<div class="targetlang"><pre>
ctype
---------
SwigObj * result;
</pre></div>
<p>
Now for each of the C++ function's arguments, a local variable with the very same type is emitted to the wrapper's body.
</p>
<div class="targetlang"><pre>
SomeTemplateClass< int > *arg1 = 0 ;
int arg2 ;
</pre></div>
<p>
If it's a C++ function that is wrapped (in this case it is), another variable is emitted for the 'original' return value of the C++ function.
At this point, we simply 'inject' behavior if it's a C++ function that is wrapped (in this case it obviously is).
</p>
<div class="targetlang"><pre>
cppouttype
-----------
SomeClass * cppresult;
</pre></div>
<p>
Next, the values of the input parameters are assigned to the local variables using the 'in' typemap.
</p>
<div class="targetlang"><pre>
{
if (carg1)
arg1 = (SomeTemplateClass< int > *) carg1->obj;
else
arg1 = (SomeTemplateClass< int > *) 0;
}
arg2 = (int) carg2;
</pre></div>
<p>
A reasonable question would be: "Why aren't the parameters assigned in the declaration of their local counterparts?"
As seen above, for complex types pointers have to be verified before extracting and
casting the actual data pointer from the provided SwigObj pointer.
This could easily become messy if it was done in the same line with the local variable declaration.
</p>
<p>
At this point we are ready to call the C++ function with our parameters.
</p>
<div class="targetlang"><pre>
{
const SomeClass &_result_ref = someFunction(*arg1,arg2);cppresult = (SomeClass*) &_result_ref;
}
</pre></div>
<p>
Subsequently, the return value is assigned to the dedicated return value variable using the 'out' typemap
</p>
<div class="targetlang"><pre>
{
result = SWIG_create_object(cppresult, SWIG_STR(SomeClass));
}
</pre></div>
<p>
Finally, the return value variable is returned.
</p>
<div class="targetlang"><pre>
return result;
</pre></div>
<p>
Note that typemaps may use <tt>$null</tt> special variable which will be
replaced with either <tt>0</tt> or nothing, depending on whether the function
has a non-void return value or not.
</p>
<H4><a name="C_walkthrough_proxy">38.6.1.3 The Proxy</a></H4>
<p>
Compared to the wrapper code generation, the header code is very simple.
Basically it contains just the declarations corresponding to the definitions
above.
</p>
<div class="targetlang"><pre>
// wrapper header file
typedef struct SwigObj_SomeClass SomeClass;
SomeClass * SomeClass_new();
void SomeClass_delete(SomeClass * carg1);
SomeClass* someFunction(SomeIntTemplateClass* carg1, int carg2);
typedef struct SwigObj_SomeIntTemplateClass SomeIntTemplateClass;
SomeIntTemplateClass * SomeIntTemplateClass_new();
void SomeIntTemplateClass_delete(SomeIntTemplateClass * carg1);
</pre></div>
<H2><a name="C_exceptions">38.7 Exception handling</a></H2>
<p>
Any call to a C++ function may throw an exception, which cannot be caught by C code. Instead, the special <tt>SWIG_CException_get_pending()</tt> function must be called to check for this. If it returns a non-null pointer, <tt>SWIG_CException_msg_get()</tt> can be called to retrieve the error message associated with the exception. Finally, <tt>SWIG_CException_reset_pending()</tt> must be called to free the exception object and reset the current pending exception. Note that exception handling is much simpler when using C++, rather than C, wrappers, see sections 36.6.2.
</p>
<H2><a name="C_cxx_wrappers">38.8 C++ Wrappers</a></H2>
<p>
When <tt>-c++</tt> command line option is used (and <tt>-nocxx</tt> one is not), the header file generated by SWIG will also contain the declarations of C++ wrapper functions and classes mirroring the original API. All C++ wrappers are fully inline, i.e. don't need to be compiled separately, and are always defined inside the namespace (or nested namespaces) specified by <tt>-namespace</tt> command-line option or the namespace with the same name as the SWIG module name if this option is not specified.
</p>
<p>
C++ wrappers try to provide a similar API to the original C++ API being wrapped, notably any class <tt>Foo</tt> in the original API appears as a class with the same name in the wrappers namespace, and has the same, or similar, public methods. A class <tt>Bar</tt> deriving from <tt>Foo</tt> also derives from it in the wrappers and so on. There are some differences with the original API, however. Some of them are due to fundamental limitations of the approach used, e.g.:
</p>
<ul>
<li>Only template instantiations are present in the wrappers, not the templates themselves.</li>
</ul>
<p>
Other ones are due to things that could be supported but haven't been implemented yet:
</p>
<ul>
<li>Only single, not multiple, inheritance is currently supported.</li>
<li>Only enums using <tt>int</tt> (or smaller type) as underlying type are supported.</li>
</ul>
<H3><a name="C_additional_possibilities">38.8.1 Additional customization possibilities</a></H3>
<p>
Generated C++ code can be customized by inserting custom code in the following sections:
</p>
<ul>
<li><tt>cxxheader</tt> for including additional headers and other declarations in the global scope.</li>
<li><tt>cxxcode</tt> for additional code to appear after the declarations of all wrapper classes, inside the module-specific namespace.</li>
</ul>
<p>
The following features are taken into account when generating C++ wrappers:
</p>
<ul>
<li><tt>cxxignore</tt> May be set to skip generation of C++ wrappers for the given function or class, while still generating C wrappers for them.</li>
</ul>
<H3><a name="C_exception_handling">38.8.2 Exception handling</a></H3>
<p>
Exception handling in C++ is more natural, as the exceptions are re-thrown when using C++ wrappers and so can be caught, as objects of the special <tt>SWIG_CException</tt> type, using the usual <tt>try/catch</tt> statement. The objects of <tt>SWIG_CException</tt> class have <tt>code()</tt> and <tt>msg()</tt> methods, with the latter returning the error message associated with the exception.
</p>
<p>
If necessary, a custom exception type may be used instead of <tt>SWIG_CException</tt>. To do this, a custom implementation of <tt>swig_check()</tt> function, called to check for the pending exception and throw the corresponding C++ exception if necessary, must be provided and <tt>SWIG_swig_check_DEFINED</tt> preprocessor symbol must be defined to prevent the default implementation of this function from being compiled:
</p>
<div class="code"><pre>
%insert(cxxheader) %{
#ifndef SWIG_swig_check_DEFINED
#define SWIG_swig_check_DEFINED 1
#include <stdexcept>
class Exception : public std::runtime_error {
public:
explicit Exception(const char* msg) : std::runtime_error{msg} {}
};
inline void swig_check() {
if (auto* swig_ex = SWIG_CException_get_pending()) {
Exception const e{SWIG_CException_msg_get(swig_ex)};
SWIG_CException_reset_pending();
throw e;
}
}
template <typename T> T swig_check(T x) {
swig_check();
return x;
}
#endif // SWIG_swig_check_DEFINED
%}
</pre></div>
</body>
</html>
|