Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpp_if not taken in account for associated method #44

Open
clementFoyer opened this issue May 29, 2019 · 4 comments
Open

cpp_if not taken in account for associated method #44

clementFoyer opened this issue May 29, 2019 · 4 comments

Comments

@clementFoyer
Copy link

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.

@ltaylor16
Copy link
Member

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.

@clementFoyer
Copy link
Author

clementFoyer commented May 30, 2019

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.

@clementFoyer
Copy link
Author

clementFoyer commented May 30, 2019

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.

@ltaylor16
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants