shroud
shroud copied to clipboard
cpp_if not taken in account for associated method
When trying to generate wrapper for the following C++ code, I end up with an error at link time when linking against the Fortran module.
C++ is like:
class Foo {
public:
void baz() {};
void bar() {};
};
I do not want to expose the symbol bar
if ENABLE_BAR
is not defined. So the YAML is such as:
declarations:
- decl: class Foo
declarations:
- decl: void baz()
- decl: void bar()
cpp_if: if defined(ENABLE_FOOBAR)
The result is such as:
type foo
type(SHROUD_foo_capsule) :: cxxmem
! splicer begin class.Foo.component_part
! splicer end class.Foo.component_part
contains
procedure :: baz => foo_baz
procedure :: bar => foo_bar
procedure :: get_instance => foo_get_instance
procedure :: set_instance => foo_set_instance
procedure :: associated => foo_associated
! splicer begin class.Foo.type_bound_procedure_part
! splicer end class.Foo.type_bound_procedure_part
end type foo
[... removing operators ...]
interface
subroutine c_foo_baz(self) &
bind(C, name="TES_foo_baz")
import :: SHROUD_foo_capsule
implicit none
type(SHROUD_foo_capsule), intent(IN) :: self
end subroutine c_foo_baz
#ifdef ENABLE_BAR
subroutine c_foo_bar(self) &
bind(C, name="TES_foo_bar")
import :: SHROUD_foo_capsule
implicit none
type(SHROUD_foo_capsule), intent(IN) :: self
end subroutine c_foo_bar
#endif
! splicer begin class.Foo.additional_interfaces
! splicer end class.Foo.additional_interfaces
end interface
contains
subroutine foo_baz(obj)
class(foo) :: obj
! splicer begin class.Foo.method.baz
call c_foo_baz(obj%cxxmem)
! splicer end class.Foo.method.baz
end subroutine foo_baz
#ifdef ENABLE_BAR
subroutine foo_bar(obj)
class(foo) :: obj
! splicer begin class.Foo.method.bar
call c_foo_bar(obj%cxxmem)
! splicer end class.Foo.method.bar
end subroutine foo_bar
#endif
[... Removing useless function implementation ...]
end module foo_mod
In the case where ENABLE_BAR
is not defined, the module will not be able to expose the foo%bar
as foo_bar
subroutine will not be defined, nor the c_foo_bar
interface.
If I define the following FORTRAN program:
program fortran_test
use foo_mod
implicit none
type(foo) :: f
call f%baz
#ifdef ENABLE_BAR
call f%bar
#endif
end program fortran_test
and try to link it to the module, I have the following error risen:
wrapfFoo.F:30:17:
procedure :: bar => foo_bar
1
Error: 'foo_bar' must be a module procedure or an external procedure with an explicit interface at (1)
One solution would be to add a check to node.cpp_if
when defining the procedure in the type definition in the wrapfFoo.f
file generated, in order to add the preprocessor directives.
Thank you for the detailed bug report. I created a branch, cpp-fortran, which adds a test and uses cpp_if for type-bound procedures. Let me know if the code will compile and load now.
Works like a charm, thanks.
Some other /error/ (or feature?) is that considering the following addition to the YAML file:
declarations:
- decl: class B
cxx_header: Bar.hpp
cpp_if: ifdef USE_B
in typeslib.h
, the wrapping structure will always be defined (potentially it uses symbols for nothing).
It seems to be some issues with how cxx_header
is taken in account as well. When I tried the following YAML:
library: testlib
declarations:
- decl: namespace testing
declarations:
- decl: void func1()
cxx_header: <stdio.h>
The cxx_header
is never taken in account and the requested headers don't appear in the wrapper header file. Neither it is when declaring within the namespace node. In order to be included, it has to be declared on the global level, or in a class node. It may be an issue as for the original example, where I would like to have the declaration of a function depending on cpp_if
, and if this function is to be wrapped, include the required header files. The same issue applies to the templates as well. If the #include <stdio.h>
was to be potentially guarded by a cpp_if
clause, that would be perfect :)
Thank you very much.
Upon further research/reading, the last point seems to be overturned by using splicer_code.c.class.{classname}.CXX_definitions
. However, an automatisation of this process would be nice, although left as a request for improvment.
EDIT: change declarations
for definitions
as the effect should be in the .cpp
file, and doesn't need to be propagated/shown outside it.
I added the use of cpp_if
in the typeslib.h
file. I think by conditionally compiling it, it makes it noticeable if it gets accidentally used.
I had not considered the idea of using cxx_header
in a function declaration. You're correct that it's only used with global and class. I'll take a look at what would be involved to use it at any level. Like you said, it would be useful combined with cpp_if
.