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:
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)
