Open ivan-pi opened 4 years ago
Yes, down the road we should generate it automatically to ensure the interface is consistent with any (future) possible changes to the C API.
Out of curiosity I pulled together the interface routines needed to run the following program:
module small_test
use symengine_cwrapper
use iso_c_binding
implicit none
contains
function c_char_ptr_to_fstring(c_char_ptr) result(fc)
type(c_ptr) :: c_char_ptr
character(len=:,kind=c_char), allocatable :: fc
character(len=1000,kind=c_char), pointer :: f_string
if (.not. c_associated(c_char_ptr)) then
fc = ""
else
call c_f_pointer(c_char_ptr,f_string)
fc = f_string(1:index(f_string,c_null_char))
end if
end function
subroutine f(i)
integer(c_long), intent(in) :: i
type(c_ptr) :: s = c_null_ptr ! string
type(c_ptr) :: x = c_null_ptr
type(c_ptr) :: y = c_null_ptr
type(c_ptr) :: e = c_null_ptr
type(c_ptr) :: n = c_null_ptr
type(c_ptr) :: exception = c_null_ptr
print *, "Symengine version: "//c_char_ptr_to_fstring(symengine_version())
call basic_new_stack(x)
call basic_new_stack(y)
call basic_new_stack(e)
call basic_new_stack(n)
exception = symbol_set(x,"x"//c_null_char)
exception = symbol_set(y,"y"//c_null_char)
exception = integer_set_si(n, i);
exception = basic_mul(e, n, x);
exception = basic_add(e, e, y);
s = basic_str(e)
print *, "Result: ", c_char_ptr_to_fstring(s)
call basic_str_free(s)
s = c_null_ptr
print *, c_associated(s), c_char_ptr_to_fstring(s)
call basic_free_stack(x)
call basic_free_stack(y)
call basic_free_stack(e)
call basic_free_stack(n)
end subroutine
end module
program small_test_program
use small_test
use iso_c_binding
implicit none
call f(5_c_long)
end program
(Note: the symengine_wrapper
module is not included because I have some mistakes left).
After figuring out all the libraries needed to install symengine, I was able to compile the example using:
gfortran -Wall -c symengine_cwrapper.f90
gfortran -Wall -c test_symengine.f90
gfortran -o test_symengine -I/usr/local/include/symengine symengine_cwrapper.o test_symengine.o -L/usr/local/lib -lsymengine -lteuchos -lstdc++ -lmpfr -lgmp -lbfd
And finally, the result of the program:
$ ./test_symengine
Symengine version: 0.6.0
Result: 5*x + y
F
Thanks! The Fortran part of the API must be improved, but it works.
On Mon, Sep 28, 2020, at 7:52 PM, Ivan wrote:
Out of curiosity I pulled together the interface routines needed to run the following program:
module small_test
use symengine_cwrapper use iso_c_binding
implicit none
contains
function c_char_ptr_to_fstring(c_char_ptr) result(fc) type(c_ptr) :: c_char_ptr character(len=:,kind=c_char), allocatable :: fc character(len=1000,kind=c_char), pointer :: f_string
if (.not. c_associated(c_char_ptr)) then fc = "" else call c_f_pointer(c_char_ptr,f_string) fc = f_string(1:index(f_string,c_null_char)) end if
end function
subroutine f(i)
integer(c_long), intent(in) :: i
type(c_ptr) :: s = c_null_ptr ! string
type(c_ptr) :: x = c_null_ptr type(c_ptr) :: y = c_null_ptr type(c_ptr) :: e = c_null_ptr type(c_ptr) :: n = c_null_ptr
type(c_ptr) :: exception = c_null_ptr
print *, "Symengine version: "//c_char_ptr_to_fstring(symengine_version())
call basic_new_stack(x) call basic_new_stack(y) call basic_new_stack(e) call basic_new_stack(n)
exception = symbol_set(x,"x"//c_null_char) exception = symbol_set(y,"y"//c_null_char)
exception = integer_set_si(n, i); exception = basic_mul(e, n, x); exception = basic_add(e, e, y);
s = basic_str(e) print *, "Result: ", c_char_ptr_to_fstring(s) call basic_str_free(s) s = c_null_ptr
print *, c_associated(s), c_char_ptr_to_fstring(s)
call basic_free_stack(x) call basic_free_stack(y) call basic_free_stack(e) call basic_free_stack(n)
end subroutine
end module
program small_test_program
use small_test use iso_c_binding implicit none
call f(5_c_long)
end program (Note: the
symengine_wrapper
module is not included because I have some mistakes left).After figuring out all the libraries needed to install symengine, I was able to compile the example using:
gfortran -Wall -c symengine_cwrapper.f90 gfortran -Wall -c test_symengine.f90 gfortran -o test_symengine -I/usr/local/include/symengine symengine_cwrapper.o test_symengine.o -L/usr/local/lib -lsymengine -lteuchos -lstdc++ -lmpfr -lgmp -lbfd
And finally, the result of the program:
$ ./test_symengine Symengine version: 0.6.0 Result: 5*x + y F
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/symengine/symengine.f90/issues/3#issuecomment-700377033, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAFAWCXC4SPA7OOFS3KBBLSIE4WRANCNFSM4R4XAFYQ.
Could you point me to the files containing the C++ API in the original symengine repository?
Typically, the high-level Fortran API can be made very similar to the C++ one.
Yes, the main C++ API is in this directory in the header files:
https://github.com/symengine/symengine/tree/master/symengine
For example the Mul
class is here:
https://github.com/symengine/symengine/blob/9fc2716cab4a6d2d89a3f9d765a04ef1594c6bcf/symengine/mul.h
The best way to understand how to use it is from tests, e.g., here:
This is the main API used throughout SymEngine. Then there is a simpler higher level API here:
https://github.com/symengine/symengine/blob/9fc2716cab4a6d2d89a3f9d765a04ef1594c6bcf/symengine/expression.h https://github.com/symengine/symengine/blob/9fc2716cab4a6d2d89a3f9d765a04ef1594c6bcf/symengine/tests/expression/test_expression.cpp
Which is just a thin wrapper to provide easier C++ interface, with a possible small performance hit.
For Fortran, I suggest we use the C interface, as it takes care of exceptions and other things, and we build whatever is the most natural in Fortran. If we can somehow overload operators in Fortran and not leak memory, that would be great.
Looking at the C header file in SymEngine, one could probably do everything manually. On the long term however, an automatic tool will probably be easier.
Would using Shroud (https://github.com/LLNL/shroud) be an option?
A presentation (PowerPoint file) is also available from FortranCon: https://tcevents.chem.uzh.ch/event/12/contributions/30/attachments/29/98/Taylor-Shroud-forcon.pptx