@@ -1013,20 +1013,49 @@ the call to `SWIG_check_unhandled_exception` ensures that no previous unhandled
1013
1013
error exists. If you wish to wrap only a few functions with only specific
1014
1014
exceptions, use the ["throws" typemap](SWIG.html#throws_typemap).
1015
1015
1016
+ The error codes (``SWIG_RuntimeError``, etc.) above will be generated as
1017
+ public Fortran parameter constants when using the `<exception.i>` header. Thus
1018
+ you can check for more specific errors as needed :
1019
+ ` ` ` fortran
1020
+ b = get_from_reference(a)
1021
+ if (ierr == SWIG_NullReferenceError) then
1022
+ write(0,*) "'a' must be allocated before passing to 'get_from_reference'"
1023
+ stop 1
1024
+ endif
1025
+ ` ` `
1026
+
1027
+ # ## Using exceptions in larger projects or software libraries
1028
+
1016
1029
When exception handling code is used, SWIG generates a few internal data
1017
1030
structures as well as two externally accessible symbols with external C linkage
1018
1031
(`ierr` and `get_serr`). Fortran bindings are generated to make the integer and
1019
1032
function accessible from the Fortran module.
1020
1033
1021
1034
The names of the integer and string accessor have C linkage and thus must
1022
- be unique in a compiled program. Since other translation units might have
1035
+ be unique in a compiled program *and* to all downstream codes linked against
1036
+ it. Since other translation units might have
1023
1037
symbols that share the default exception handling names, the user can provide
1024
- custom names before including the exception handling file :
1038
+ custom names before including the exception handling file. A `%rename`
1039
+ directive can then reset the Fortran proxy name to something simpler while
1040
+ retaining the scoped C linkage variable names.
1041
+
1042
+ In this example, the C-linkage variables generated will be `_scoped_ierr` and `_scoped_get_serr` :
1025
1043
` ` ` swig
1026
- #define SWIG_FORTRAN_ERROR_INT my_ierr
1027
- #define SWIG_FORTRAN_ERROR_STR get_my_serr
1044
+ %module foo;
1045
+
1046
+ #define SWIG_FORTRAN_ERROR_INT scoped_ierr
1047
+ #define SWIG_FORTRAN_ERROR_STR scoped_get_serr
1048
+ %rename(ierr) scoped_ierr;
1049
+ %rename(get_serr) scoped_get_serr;
1028
1050
%include <std_except.i>
1029
1051
` ` `
1052
+ but because of the %rename directives, they can still be accessed from Fortran
1053
+ with simpler names since they are "scoped" to the generated module :
1054
+ ` ` ` fortran
1055
+ use foo, only : ierr, get_serr
1056
+ ` ` `
1057
+
1058
+ # ## Exceptions with multiple modules
1030
1059
1031
1060
If you're linking multiple modules together (using %import or otherwise), only
1032
1061
one of those modules should define the error integer and accessor by including
@@ -1552,7 +1581,8 @@ A single Fortran proxy class must be able to act as a value, a pointer, or a
1552
1581
reference to a C++ class instance.
1553
1582
When stored as a value, a method must be put in place to deallocate the
1554
1583
associated memory; if the instance is a reference, that same method cannot
1555
- double-delete the associated memory. Finally, C++ functions
1584
+ double-delete the associated memory. An additional complication is that C++
1585
+ functions
1556
1586
must be able to send Fortran pointers both *with and without* owning the
1557
1587
associated memory, depending on the function. Finally,
1558
1588
assignment between Fortran classes must preserve memory association.
@@ -1595,23 +1625,14 @@ temporary's memory. Unfortunately, only the very latest compilers (as of 2018,
1595
1625
14 years after the standard was ratified) have full support for the `FINAL` keyword.
1596
1626
1597
1627
Our solution to this limitation is to have the `Foo` proxy class store not only
1598
- a pointer to the C data but also a state enumeration `self%swigdata%mem` that
1599
- describes memory ownership. The enumeration needs to have at least three options :
1600
-
1601
- - The memory is *owned* by the proxy class (and must be deleted when calling
1602
- ` release()` );
1603
- - The proxy class is a *reference* to memory owned by C/C++ (returned by either
1604
- a raw pointer or a reference);
1605
- - The memory is being allocated and returned from a function, but it must be
1606
- captured by the left hand side.
1607
-
1608
- This last option is roughly analogous to the behavior of the deprecated
1609
- ` std::auto_ptr` , which was the predecessor to C++11's `move` semantics.
1610
- Besides the above flags, we also define an uninitialized state `NULL` for
1611
- convenience, and a "const reference" state to enable const correctness. These
1612
- flags are set by the SWIG `out` typemaps in the C wrapper code : if memory is
1613
- being allocated, the return flag is `MOVE`; if a pointer is being returned,
1614
- ` REF` (or `CREF` in the const case) is used.
1628
+ a pointer to the C data (`self%swigdata%cptr`) but also a set of state flags
1629
+ (`self%swigdata%cmemflags`) that describes memory ownership.
1630
+ Currently there are two flags :
1631
+
1632
+ - Ownership (the `swig_cmem_own_bit` in Fortran wrapper code) is true if
1633
+ freeing the wrapper should destroy and free the corresponding C/C++ memory.
1634
+ - If ownership of the class instance is being transferred from a function, the
1635
+ ` rvalue` bit is set (`swig_cmem_rvalue_bit`).
1615
1636
1616
1637
The crucial trick is to implement an assignment operator that correctly copies,
1617
1638
allocates, or moves memory based on the flags on the left- and right-hand sides,
@@ -1633,19 +1654,15 @@ omitted.
1633
1654
| NULL | NULL | (none) |
1634
1655
| NULL | MOVE | `pself = pother;` |
1635
1656
| NULL | OWN | `pself = new This(pother);` |
1636
- | NULL | REF/CREF | `pself = pother;` |
1657
+ | NULL | REF | `pself = pother;` |
1637
1658
| OWN | NULL | `delete pself; pself = NULL;` |
1638
1659
| OWN | MOVE | `*pself = move(*pother); delete pother;`|
1639
1660
| OWN | OWN | `*pself = *pother;` |
1640
- | OWN | REF/CREF | `*pself = *pother;` |
1661
+ | OWN | REF | `*pself = *pother;` |
1641
1662
| REF | NULL | `pself = NULL;` |
1642
1663
| REF | MOVE | `*pself = move(*pother); delete pother;`|
1643
1664
| REF | OWN | `*pself = *pother; ` |
1644
- | REF | REF/CREF | `*pself = *pother;` |
1645
- | CREF | NULL | `pself = NULL;` |
1646
- | CREF | MOVE | (error) |
1647
- | CREF | OWN | (error) |
1648
- | CREF | REF/CREF | (error) |
1665
+ | REF | REF | `*pself = *pother;` |
1649
1666
1650
1667
The above operations are designed to preserve C++ semantics : if an proxy object
1651
1668
owning memory is assigned, then any existing objects pointing to that memory
0 commit comments