Bad value being read from Fortran class variable

Viewed 100

I'm trying to make a simple Fortran-C binding program, but I'm stuck at a pretty basic concept - printing value from a member variable.

Despite I set it to the value 5, I'm receiving random numbers back - obviously a memory problem. It seems, that the problem is right at print_vsize() method, but I have no idea, what can be wrong here.

I also tried to look at the instance in Debug mode and it seems, that some internal structure is being constructed in the class:

enter image description here

1) Could you, please, provide any advice about what can be wrong with my code?

2) Is it possible to apply the same principle for arrays passed as parameters?


main.f90

program test
    use iso_c_binding
    use myclassbind

    implicit none

    type(myclass) :: instance


    instance = myclass(5)
    call instance%print_vsize()

end program test

myClass_c_mod.f90

module myclassbind
    use iso_c_binding

    implicit none

    private
    public :: myclass

    type myclass
        private
        type(c_ptr) :: ptr

    contains
        procedure :: print_vsize => print_vsize_impl
    end type

    interface myclass
        module procedure create_myclass
    end interface

    interface

        function create_myclass_c(n) bind(C, name="create_myclass_c")
            use iso_c_binding
            implicit none

            type(c_ptr) :: create_myclass_c
            integer(c_int), value :: n
        end function

        subroutine print_vsize_c(obj) bind(C, name="print_vsize_c")
            use iso_c_binding
            implicit none
            type(c_ptr) :: obj
        end subroutine print_vsize_c
    end interface

contains

    function create_myclass(n)
        implicit none
        type(myclass) :: create_myclass
        integer(c_int), intent(in) :: n
        create_myclass%ptr = create_myclass_c(n)
    end function

    subroutine print_vsize_impl(this)
        implicit none
        class(myclass) :: this
        call print_vsize_c(this%ptr)
    end subroutine print_vsize_impl
end module

myClass_c.h

#ifndef FORTRANBIND_MYCLASS_C_H
#define FORTRANBIND_MYCLASS_C_H

#ifdef __cplusplus
extern "C" {
    class myClass;
    typedef myClass MYCLASS;
#else
    typedef struct MYCLASS MYCLASS;
#endif

    MYCLASS* create_myclass_c(int n);
    void print_vsize_c(MYCLASS* obj_ptr);

#ifdef __cplusplus
}
#endif

#endif //FORTRANBIND_MYCLASS_C_H

myClass_c.cpp

#include <vector>

#include "myClass.h"
#include "myClass_c.h"

MYCLASS* create_myclass_c(int n) {
    return new myClass(n);
}

void print_vsize_c(MYCLASS* obj_ptr) {
    obj_ptr->print_vsize();
}

myClass.h

#ifndef FORTRANBIND_MYCLASS_H
#define FORTRANBIND_MYCLASS_H

#include <iostream>
#include <vector>

class myClass {
private:
    int n;

public:
    explicit myClass(int n);
    void print_vsize();
};

#endif //FORTRANBIND_MYCLASS_H

myClass.cpp

#include "myClass.h"


myClass::myClass(int n) {
    this->n = n;
}

void myClass::print_vsize() {
    std::cout << this->n << std::endl;
}

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
PROJECT(FortranBind C CXX Fortran)

SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_Fortran_STANDARD 2008)

ADD_EXECUTABLE(FortranBind main.f90)
TARGET_LINK_LIBRARIES(FortranBind PUBLIC myClass_c_mod )

ADD_LIBRARY(myClass_c_mod myClass_c_mod.f90 myClass.cpp myClass_c.cpp)

0 Answers
Related