Skip to content

Commit 00a121d

Browse files
committed
Add director support for bools
1 parent 7a14f7d commit 00a121d

File tree

7 files changed

+171
-103
lines changed

7 files changed

+171
-103
lines changed

Examples/test-suite/common.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ CPP_TEST_CASES += \
208208
director_protected_overloaded \
209209
director_redefined \
210210
director_ref \
211+
director_simple \
211212
director_smartptr \
212213
director_thread \
213214
director_unroll \

Examples/test-suite/director_int.i

Lines changed: 0 additions & 26 deletions
This file was deleted.

Examples/test-suite/director_simple.i

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
%module(directors="1") director_simple
2+
3+
%feature("director") IntBase;
4+
%feature("director") BoolBase;
5+
6+
%inline %{
7+
class IntBase {
8+
public:
9+
virtual ~IntBase() {}
10+
IntBase(int i = 3) { (void)i; }
11+
virtual int apply(int x) const { return x * 2; }
12+
};
13+
14+
class IntDerived : public IntBase {
15+
public:
16+
virtual int apply(int x) const { return x * 3; }
17+
};
18+
19+
int apply(const IntBase& b, int x)
20+
{
21+
return b.apply(x);
22+
}
23+
24+
class BoolBase {
25+
public:
26+
virtual ~BoolBase() {}
27+
BoolBase() {}
28+
virtual bool apply(bool a, bool b) const = 0;
29+
};
30+
31+
class BoolDerived : public BoolBase {
32+
public:
33+
virtual bool apply(bool a, bool b) const { return a != b; }
34+
};
35+
36+
bool apply(const BoolBase& base, bool a, bool b)
37+
{
38+
return base.apply(a, b);
39+
}
40+
41+
%}
42+

Examples/test-suite/fortran/director_int_runme.F90

Lines changed: 0 additions & 76 deletions
This file was deleted.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
! File : director_simple_runme.F90
2+
3+
#include "fassert.h"
4+
5+
module director_simple_mod
6+
use, intrinsic :: ISO_C_BINDING
7+
use ISO_FORTRAN_ENV
8+
use director_simple, only : IntBase, BoolBase
9+
implicit none
10+
11+
type, extends(IntBase), public :: MyIntDerived
12+
integer(C_INT) :: multiply_by = 1
13+
integer(C_INT) :: add_to = 0
14+
contains
15+
procedure :: apply => MyIntDerived_apply
16+
end type MyIntDerived
17+
18+
type, extends(BoolBase), public :: MyBoolDerived
19+
integer :: call_count = 0
20+
contains
21+
procedure :: apply => MyBoolDerived_apply
22+
end type MyBoolDerived
23+
24+
contains
25+
26+
function MyIntDerived_apply(self, x) &
27+
result(myresult)
28+
use, intrinsic :: ISO_C_BINDING
29+
class(MyIntDerived) :: self
30+
integer(C_INT), intent(in) :: x
31+
integer(C_INT) :: myresult
32+
33+
myresult = x * self%multiply_by + self%add_to
34+
end function
35+
36+
function MyBoolDerived_apply(self, a, b) &
37+
result(myresult)
38+
use, intrinsic :: ISO_C_BINDING
39+
class(MyBoolDerived) :: self
40+
logical, intent(in) :: a
41+
logical, intent(in) :: b
42+
logical :: myresult
43+
44+
myresult = a .or. b
45+
self%call_count = self%call_count + 1
46+
end function
47+
48+
end module
49+
50+
program director_simple_runme
51+
call test_director_int
52+
call test_director_bool
53+
contains
54+
55+
subroutine test_director_int
56+
use director_simple
57+
use director_simple_mod
58+
use, intrinsic :: ISO_C_BINDING
59+
type(MyIntDerived), target :: myclass
60+
class(IntBase), pointer :: baseptr => NULL()
61+
class(IntBase), allocatable :: alloc
62+
63+
! Allocate and set up callbacks for IntBase class
64+
call swig_initialize(myclass, source=IntBase())
65+
myclass%multiply_by = 2
66+
myclass%add_to = 1
67+
68+
! Direct Fortran call
69+
ASSERT(myclass%apply(10_c_int) == 21_c_int)
70+
! Call through C director
71+
ASSERT(apply(myclass, 10_c_int) == 21_c_int)
72+
! Call through C via IntBase pointer
73+
baseptr => myclass
74+
ASSERT(apply(baseptr, 10_c_int) == 21_c_int)
75+
76+
myclass%multiply_by = 3
77+
ASSERT(apply(baseptr, 10_c_int) == 31_c_int)
78+
79+
call myclass%release()
80+
81+
! Allocate a C++ daughter class and call it as well
82+
allocate(alloc, source=IntBase())
83+
ASSERT(apply(alloc, 2_c_int) == 4_c_int)
84+
call alloc%release()
85+
deallocate(alloc)
86+
87+
allocate(alloc, source=IntDerived())
88+
ASSERT(apply(alloc, 2_c_int) == 6_c_int)
89+
call alloc%release()
90+
deallocate(alloc)
91+
92+
end subroutine
93+
94+
subroutine test_director_bool
95+
use director_simple
96+
use director_simple_mod
97+
use, intrinsic :: ISO_C_BINDING
98+
type(MyBoolDerived), target :: myclass
99+
100+
! Allocate and set up callbacks for BoolBase class
101+
call swig_initialize(myclass, source=BoolBase())
102+
103+
! Direct Fortran call
104+
ASSERT(myclass%apply(.true., .false.))
105+
ASSERT(.not. myclass%apply(.false., .false.))
106+
! Call through C director
107+
ASSERT(apply(myclass, .true., .false.))
108+
ASSERT(.not. apply(myclass, .false., .false.))
109+
ASSERT(myclass%call_count == 4)
110+
111+
call myclass%release()
112+
113+
end subroutine
114+
end program
115+
116+

Lib/fortran/classes.swg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ SWIGINTERN void SWIG_assign(SwigClassWrapper* self, SwigClassWrapper other) {
352352
// Raw pointers act mostly like value types, but they don't have to accept the exact type (polymorphic input, non-polymorphic output). Intent is 'in' because
353353
// we're not modifying the pointer or memory status.
354354
%apply SWIGTYPE { SWIGTYPE* };
355-
%typemap(ftype, in="class($fortranclassname), intent(in)", nofortransubroutine=1) SWIGTYPE*
355+
%typemap(ftype, in="class($fortranclassname)", nofortransubroutine=1) SWIGTYPE*
356356
"type($fortranclassname)"
357357
%typemap(in, noblock=1) SWIGTYPE* {
358358
$1 = ($1_ltype)$input->cptr;

Lib/fortran/fundamental.swg

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ SWIGINTERN SwigArrayWrapper SwigArrayWrapper_uninitialized() {
100100
%typemap(fout, fragment="SWIG_fout"{CPPTYPE}, noblock=1) MATCHTYPE {
101101
call %fortrantm(fout, CPPTYPE)($1, $result)
102102
}
103+
%typemap(fdirectorin, fragment="SWIG_fout"{CPPTYPE}, noblock=1) MATCHTYPE {
104+
call %fortrantm(fout, CPPTYPE)($input, $1)
105+
}
106+
%typemap(fdirectorout, fragment="SWIG_fin"{CPPTYPE}, noblock=1) MATCHTYPE {
107+
call %fortrantm(fin, CPPTYPE)($1, $result)
108+
}
103109
%enddef
104110

105111
/*!
@@ -395,6 +401,11 @@ $input = &temp;%}
395401
// Define special fin/fout typemaps for logical<->c_int
396402
%fortran_typemap_finout(bool, bool)
397403

404+
%typemap(directorin, noblock=1) bool (int temp)
405+
%{temp = $1 ? 1 : 0;
406+
$input = &temp;%}
407+
%typemap(directorout) bool "$result = (bool)$1;"
408+
398409
// Treat const references like values
399410
%apply bool { const bool& };
400411
// ... except our 'in' typemap has to create a temporary

0 commit comments

Comments
 (0)