|
2 | 2 | * memfunptr.swg
|
3 | 3 | * ------------------------------------------------------------------------- */
|
4 | 4 |
|
5 |
| -/* The size of the opaque object that stores the member function pointer. |
6 |
| - * |
7 |
| - * This could be overridden by generating a config.h file with the actual |
8 |
| - * maximum function pointer size and %include-ing that configure file in |
9 |
| - * a local fortranfragments.swg file. */ |
10 |
| -#ifndef SWIG_MEMFUNPTR_SIZE |
11 |
| -%define SWIG_MEMFUNPTR_SIZE 32 %enddef |
12 |
| -#endif |
13 |
| - |
14 |
| -/* ------------------------------------------------------------------------- |
15 |
| - * BRUTE CAST |
16 |
| - * ------------------------------------------------------------------------- */ |
17 |
| - |
18 |
| -// This fragment allows making an opaque datatype from C++ member function |
19 |
| -// pointers (which according to the standard CANNOT be converted to a pointer). |
20 |
| -// encountered. Its syntax is exactly like static_cast. |
21 |
| -// Note that the <string.h> fragment imports size_t into the global namespace. |
22 |
| -%fragment("swig::brute_cast", "header", fragment="<string.h>") %{ |
23 |
| -template<typename Dst, typename Src> |
24 |
| -SWIGINTERN void SWIG_opaque_memcpy(Dst *dst, const Src *src) { |
25 |
| - const size_t MINSIZE |
26 |
| - = (sizeof(Dst) < sizeof(Src) ? sizeof(Dst) : sizeof(Src)); |
27 |
| - const size_t MAXSIZE |
28 |
| - = (sizeof(Dst) > sizeof(Src) ? sizeof(Dst) : sizeof(Src)); |
29 |
| - memcpy(dst, src, MINSIZE); |
30 |
| - if (MAXSIZE > MINSIZE) |
31 |
| - { |
32 |
| - memset(static_cast<char*>(static_cast<void*>(dst)) + MINSIZE, |
33 |
| - 0, |
34 |
| - MAXSIZE - MINSIZE); |
35 |
| - } |
36 |
| -} |
37 |
| - |
38 |
| -namespace swig { |
39 |
| -template<typename Target> |
40 |
| -class brute_cast_impl { |
41 |
| - public: |
42 |
| - template<typename Source> |
43 |
| - brute_cast_impl(const Source &src_fwd) { |
44 |
| - SWIG_opaque_memcpy(&d_result, &src_fwd); |
45 |
| - } |
46 |
| - Target operator() () const { return d_result; } |
| 5 | +%fragment("SwigFortranPackedData", "header", |
| 6 | + fragment="<string.h>", fragment="<stdlib.h>") %{ |
| 7 | +class SwigFortranPackedData { |
47 | 8 | private:
|
48 |
| - Target d_result; |
49 |
| -}; |
| 9 | + char* packed_; |
50 | 10 |
|
51 |
| -template<typename Target> |
52 |
| -class brute_cast_impl<Target&> { |
53 | 11 | public:
|
54 |
| - template<typename Source> |
55 |
| - brute_cast_impl(Source& src_ref) { |
56 |
| - Source *src_ptr = &src_ref; |
57 |
| - SWIG_opaque_memcpy(&d_result, &src_ptr); |
58 |
| - } |
59 |
| - Target &operator() () const { return *d_result; } |
60 |
| - private: |
61 |
| - Target *d_result; |
62 |
| -}; |
63 |
| - |
64 |
| -template<class Target, class Source> |
65 |
| -SWIGINTERN Target brute_cast(const Source& src) { |
66 |
| - return brute_cast_impl<Target>(src)(); |
67 |
| -} |
68 |
| -} // end namespace swig |
69 |
| - |
70 |
| -using swig::brute_cast; |
71 |
| -%} |
| 12 | + template<class T> |
| 13 | + SwigFortranPackedData(const T* data) { |
| 14 | + packed_ = (char *)malloc(sizeof(T)); |
| 15 | + memcpy(packed_, data, sizeof(T)); |
| 16 | + } |
72 | 17 |
|
73 |
| -/* ------------------------------------------------------------------------- |
74 |
| - * MEMBER FUNCTION POINTERS |
75 |
| - * |
76 |
| - * We memcpy the member function pointer to an opaque data class using |
77 |
| - * brute_cast. |
78 |
| - * ------------------------------------------------------------------------- */ |
| 18 | + ~SwigFortranPackedData() { free(packed_); } |
79 | 19 |
|
80 |
| -// Add array wrapper to C++ code when used by Fortran fragment |
81 |
| -%fragment("SwigOpaqueMemFunPtr", "header", noblock=1, fragment="<string.h>") { |
82 |
| -%#if __cplusplus >= 201103L |
83 |
| -namespace detail { class UndefinedClass; } |
84 |
| -%#endif |
| 20 | + template<class T> |
| 21 | + void unpack(T* data) const { |
| 22 | + memcpy(data, packed_, sizeof(T)); |
| 23 | + } |
85 | 24 |
|
86 |
| -struct SwigOpaqueMemFunPtr { |
87 |
| - char data[SWIG_MEMFUNPTR_SIZE]; |
88 |
| -%#if __cplusplus >= 201103L |
89 |
| - static_assert(sizeof(void (detail::UndefinedClass::*)()) <= SWIG_MEMFUNPTR_SIZE, |
90 |
| - "Member pointer buffer isn't large enough"); |
91 |
| -%#endif |
| 25 | + private: |
| 26 | + SwigFortranPackedData& operator=(const SwigFortranPackedData& other); |
92 | 27 | };
|
93 |
| - |
94 |
| -SWIGINTERN SwigOpaqueMemFunPtr SwigOpaqueMemFunPtr_uninitialized() { |
95 |
| - SwigOpaqueMemFunPtr result; |
96 |
| - memset(result.data, 0, sizeof(result.data)); |
97 |
| - return result; |
98 |
| -} |
99 |
| -} |
100 |
| - |
101 |
| -// This fragment is inserted by the fortran.cxx code when an unknown class is |
102 |
| -// encountered. Note for this to compile and not crash, the size of 'data' should |
103 |
| -// be the same size as in SwigOpaqueMemFunPtr. |
104 |
| -%fragment("SwigOpaqueMemFunPtr_f", "fdecl", noblock=1, fragment="SwigOpaqueMemFunPtr") |
105 |
| -{ type, public, bind(C) :: SwigOpaqueMemFunPtr |
106 |
| - integer(C_SIGNED_CHAR), dimension(SWIG_MEMFUNPTR_SIZE), public :: data |
107 |
| - end type} |
| 28 | +%} |
108 | 29 |
|
109 | 30 | /* -------------------------------------------------------------------------
|
110 | 31 | * TYPEMAPS
|
111 | 32 | * ------------------------------------------------------------------------- */
|
112 | 33 |
|
113 |
| -%typemap(ctype, fragment="SwigOpaqueMemFunPtr", |
114 |
| - null="SwigOpaqueMemFunPtr_uninitialized()") SWIGTYPE (CLASS::*) |
115 |
| - "SwigOpaqueMemFunPtr" |
116 |
| -%typemap(imtype, in="type(SwigOpaqueMemFunPtr), intent(in), value", |
117 |
| - fragment="SwigOpaqueMemFunPtr_f") SWIGTYPE (CLASS::*) |
118 |
| - "type(SwigOpaqueMemFunPtr)" |
119 |
| -%typemap(ftype, in="type(SwigOpaqueMemFunPtr), intent(in), value", |
120 |
| - fragment="SwigOpaqueMemFunPtr_f") SWIGTYPE (CLASS::*) |
121 |
| - "type(SwigOpaqueMemFunPtr)" |
122 |
| - |
123 |
| -%typemap(in, noblock=1, fragment="swig::brute_cast") SWIGTYPE (CLASS::*) { |
124 |
| - $1 = brute_cast<$1_ltype>($input); |
125 |
| -} |
126 |
| -%typemap(out, noblock=1, fragment="swig::brute_cast") SWIGTYPE (CLASS::*) { |
127 |
| - $result = brute_cast<SwigOpaqueMemFunPtr>($1); |
| 34 | +%typemap(in, noblock=1, fragment="SwigFortranPackedData") SWIGTYPE (CLASS::*) { |
| 35 | + ((SwigFortranPackedData*)($input->cptr))->unpack<$1_ltype>(&$1); |
128 | 36 | }
|
129 |
| -%typemap(fin) SWIGTYPE (CLASS::*) |
130 |
| - "$1 = $input" |
131 |
| -%typemap(fout) SWIGTYPE (CLASS::*) |
132 |
| - "$result = $1" |
133 | 37 |
|
134 |
| -%typemap(bindc, in="type(C_FUNPTR), value", |
135 |
| - fragment="SwigOpaqueMemFunPtr_f") SWIGTYPE (CLASS::*) |
136 |
| - "type(SwigOpaqueMemFunPtr)" |
| 38 | +%typemap(out, noblock=1, fragment="SwigFortranPackedData") SWIGTYPE (CLASS::*) { |
| 39 | + $result.cptr = new SwigFortranPackedData(&$1); |
| 40 | + $result.cmemflags = SWIG_MEM_RVALUE | SWIG_MEM_OWN; |
| 41 | +} |
137 | 42 |
|
138 | 43 | // The SWIG type system does not check the non-const memfunptr when looking for a const memfunptr. Also apply
|
139 | 44 | %apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::* const) };
|
140 | 45 |
|
141 |
| -// I'm not sure this is correct, but it allows member_funcptr_galore to pass. |
142 |
| -%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::* const &)}; |
| 46 | +// References to member function pointers will look like regular class references |
| 47 | +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } |
0 commit comments