Commit ef980a04 authored by Mozul Rémy's avatar Mozul Rémy
Browse files

attemp to map in python datastructure allocated within fortran

parent 2e8f1323
typedef struct
{
int itype;
double val;
char field[30];
} C_param;
typedef struct
{
char nickname[30];
double rsingle;
int isingle;
int itab[2]; //contains sizes of rtab and weird in that order
double * rtab;
C_param * weird;
} C_datatype;
void getOne(int id, C_datatype * d);
void display(int id);
void change(int id, char * nn, double rv, int iv);
cdef extern from 'dtype.h':
ctypedef struct C_param:
int itype
double val
char field[30]
ctypedef struct C_datatype:
char nickname[30]
double rsingle
int isingle
int itab[2] #contain sizes of rtab and weird in that order
double * rtab
C_param * weird
void getOne(int id, C_datatype * d)
void display(int id)
void change(int id, char * nn, double rv, int iv)
cimport numpy as np
import numpy as np
import cython as ct
from dtype cimport C_param, C_datatype, getOne, display, change
np.import_array()
cdef class P_datatype(object):
cdef int id
cdef C_datatype f_image
cdef public np.ndarray rtab
@ct.locals(i=int)
def __init__(self, i):
self.id = i
getOne(i,&self.f_image)
self.rtab = np.PyArray_SimpleNewFromData(1, [self.f_image.itab[0]], np.NPY_DOUBLE, self.f_image.rtab)
def cythonChange(self,nn,rv,iv):
#&self.f_image.nickname[0] = nn
self.f_image.rsingle = rv
self.f_image.isingle = iv
def fortranChange(self,nn,rv,iv):
change(self.id, nn, rv, iv)
def getWeirdCopy(self,i):
if i < self.f_image.itab[1]:
return self.f_image.weird[i]
else:
raise IndexError
def fortranContent(self):
display(self.id)
def cythonContent(self):
cdef int i
print self.f_image.nickname
print self.f_image.rsingle
print self.f_image.isingle
for i in range(self.f_image.itab[0]):
print self.f_image.rtab[i]
print self.rtab
for i in range(self.f_image.itab[1]):
print self.f_image.weird[i]
all: dtype.so
libdtype.so: mod_dtype.f90
gfortran -shared -o $@ $<
dtype.so: dtype.pyx libdtype.so
python setup.py build_ext -i
clean:
@rm -f *.so *.c *.mod
module data_type
use iso_c_binding
implicit none
private
! an intermediate type
type, bind(c) :: T_param
integer(kind=c_int) :: itype
real(kind=c_double) :: val
character(kind=c_char,len=30) :: field
end type T_param
! the real type to bind
type, bind(c) :: T_datatype
! a string of size 30
character(kind=c_char,len=30) :: nickname
! a real alone
real(kind=c_double) :: rsingle
! an integer alone
integer(kind=c_int) :: isingle
! a fixed size array :
! contains the sizes of rtab and weird arrays in that order
integer(kind=c_int), dimension(2) :: itab
! a dynamic array
! doesn't work like this : real(kind=c_double), dimension(:), pointer :: rtab
type(c_ptr) :: rtab
! a pointer on an array of an interoperable type
!type(T_param), dimension(:), pointer :: weird => null()
type(c_ptr) :: weird
end type T_datatype
type(T_datatype), dimension(:), allocatable :: mydatas
!----------------------------------------------------------------------
integer :: nb_data = 0
! --------------------------
! subroutines set to private
! --------------------------
! none
! -------------------------
! subroutines set to public
! -------------------------
! wrap API
public get_one
contains
subroutine get_one(id, d) bind(c, name='getOne')
implicit none
integer(kind=c_int), intent(in), value :: id
type(T_datatype) :: d
!
logical, save :: is_first = .true.
integer(kind=4) :: i
real(kind=8) , dimension(:), pointer :: rtab
type(T_param), dimension(:), pointer :: weird
if( is_first ) then
allocate(mydatas(1))
mydatas(1)%nickname = "data in fortran"
mydatas(1)%rsingle = 1.d0
mydatas(1)%isingle = 1
mydatas(1)%itab = (/2,3/)
allocate(rtab(2))
rtab = (/0.1d0,0.2d0/)
mydatas(1)%rtab = c_loc(rtab(1))
allocate(weird(3))
do i = 1, 3
weird(i)%itype = i
weird(i)%val = 1.
write(weird(i)%field,'(A,I0)') 'field of ',i
end do
mydatas(1)%weird = c_loc(weird(1))
is_first = .false.
end if
d = mydatas(1)
end subroutine
subroutine display(id) bind(c, name='display')
implicit none
integer(kind=c_int), intent(in), value :: id
!
integer(kind=4) :: i
real(kind=8) , dimension(:), pointer :: rtab
type(T_param), dimension(:), pointer :: weird
print *,'T_DATA of id ', id
print *,' nickname : ', mydatas(id)%nickname
print *,' rsingle : ', mydatas(id)%rsingle
print *,' isingle : ', mydatas(id)%isingle
print *,' itab : ', mydatas(id)%itab
call c_f_pointer(mydatas(id)%rtab,rtab,(/mydatas(id)%itab(1)/))
call c_f_pointer(mydatas(id)%weird,weird,(/mydatas(id)%itab(2)/))
print *,' rtab : ', rtab
do i = 1, mydatas(id)%itab(2)
print *,' weird : ', i
print *,' --itype : ', weird(i)%itype
print *,' --val : ', weird(i)%val
print *,' --field : ', weird(i)%field
end do
end subroutine
subroutine change(id, nn, rv, iv) bind(c, name='change')
implicit none
integer(kind=c_int), intent(in), value :: id
real(kind=c_double), intent(in), value :: rv
integer(kind=c_int), intent(in), value :: iv
type(c_ptr), value :: nn
!
character(kind=c_char,len=30), pointer :: nname
integer(kind=4) :: i
call c_f_pointer(cptr=nn,fptr=nname)
i = 0
do while( i <30 .and. nname(i+1:i+1) /= c_null_char )
i = i + 1
end do
mydatas(id)%nickname(1:i) = nname(1:i)
mydatas(id)%nickname(i+1:) = ''
mydatas(id)%rsingle = rv
mydatas(id)%isingle = iv
end subroutine
end module data_type
import os
import numpy
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(name='sprint',
ext_modules=[Extension('dtype',['dtype.pyx'],
libraries=['dtype'],
library_dirs=[os.getcwd()],
include_dirs=[numpy.get_include()])],
cmdclass={'build_ext':build_ext}
)
import dtype
dat = dtype.P_datatype(1)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment