Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28548 ディスカッション

connecting from Fortran to MySQL via C API

新規コントリビューター III

Hi all,

in our MPI C(++)/Fortran mixed code project (Linux x64 and Windows x64) MySQL is partly used in the C-part to transfer data between master and slave process. Now it is necessary also to connect some Fortran-slave parts to MySQL.

One solution could be to use only C to connect to MySQL and push the data to Fortran over the interface. This solution is not nice because it will blow up the interface in a way which makes it prone to errors and debugging won't be easy.

The second solution could be to use the mysql.f90 wrapper out of FLIBS (, many thanks to Daniel Kraft and arjenmarkus). In this point I'm stuck because I am not familiar with the use of pointers in iso_c_binding and the necessay declation of data types in the Fortran part from where I make the call.

For example, the connection function to a MySQL service out of mysql.f90 says:

    FUNCTION c_connect (mysql, host, user, pwd, db, port, socket, flags) &
    BIND(C, NAME='mysql_real_connect')
      TYPE(C_PTR) :: c_connect
      TYPE(C_PTR), VALUE :: mysql
      CHARACTER(C_CHAR), DIMENSION(*) :: host, user, pwd, db
      INTEGER(C_INT), VALUE :: port
      TYPE(C_PTR), VALUE :: socket
      INTEGER(C_INT), VALUE :: flags
    END FUNCTION c_connect

How do I call this function from my Fortran main code and how have the parameters to be declared there?

    character(len=80)    :: host, user, pwd, db
    integer(kind=4)      :: port, flags
    type(c_ptr)          :: mysql, socket
    type(c_ptr)          :: MySQLConRet

    ... assign variables ...

    MySQLConRet = c_connect(mysql, host, user, pwd, db, port, socket, flags)

This was my not working approach.

I've read this and , but unluckily the attachments cannot be downloaded anymore, so that the examples are lost.

Any help will be welcome :-)

Kind regards, Johannes

0 件の賞賛
5 返答(返信)
新規コントリビューター III
OK, read first, then ask! The answer was still there in mysql.f90. FUNCTION myfortran_connect gives an example of how to call it correctly. character(len=80) :: host, user, pwd, db integer(kind=4) :: port, flags type(c_ptr) :: mysql, socket type(myfortran) :: MySQLConRet ... assign variables ... MySQLConRet = myfortran_connect(host, user, pwd, db) This is how it works now.
新規コントリビューター III
Hi there, here is a little update (if anybody is interested in my monologue ;-) ):
If I limit the character pointer in the write statement to
[fortran]write(*,*) 'MySQL Connection Info: ', t0dumy_ptr(1:20)[/fortran]
then I will get the correct message in the console window: MySQL Connection Info: via TCP/IP Very curious... Johannes
新規コントリビューター III
Dear all, once I found the solution for the problem above I was playing around a little bit with the Fortran-C API-Interface to MySQL and found some strange behaviour of character data. I extended the original mysql.f90 of FLIBS to mysql_get_host_info. The interface is: [fortran] FUNCTION c_get_host_info (mysql) & BIND(C, NAME='mysql_get_host_info') USE ISO_C_BINDING IMPLICIT NONE TYPE(c_ptr) :: c_get_host_info TYPE(C_PTR), VALUE :: mysql END FUNCTION c_get_host_info [/fortran] and the wrapper says: [fortran] ! get host info FUNCTION mysql_get_host_info (myf) use iso_c_binding IMPLICIT NONE TYPE(myfortran), INTENT(IN) :: myf TYPE(c_ptr) :: c_string_ptr character(len=200),pointer :: mysql_get_host_info c_string_ptr = c_get_host_info(myf%mysql) call c_f_pointer(c_string_ptr, mysql_get_host_info) END FUNCTION mysql_get_host_info [/fortran] the call in my main program is: t0dumy_ptr => mysql_get_host_info(MySQLConnect) ! t0dumy_ptr is a character(200),pointer If I write this pointer on console I got this: write(*,*) 'MySQL Connection Info: ', t0dumy_ptr --> please open console_output.png in the attached zip The debug watch window gives me the expected result: ' via TCP/IP ' The output in a text file delivers again strange data: test.txt in the zip What is wrong here? Isn't it possible to get the right information out of a c_ptr character? Why are there differences between watch window and console output? Any help is welcome! Kind regards, Johannes
名誉コントリビューター II
The string has a NULL in it, after "TCP/IP". That probably indicates the end of the string as returned by the underlying function call - the rest of your character variable is likely to be garbage. (Alternatively, there's another null after the IP address - perhaps two strings are being returned - I'm not familiar with the function you are calling.). The Visual Studio debug output is chopping off the string at that point - the console output simply shows the garbage (because there are control characters in that garbage the console output overwrites itself). You could use INDEX(t0dummy_ptr, ACHAR(0)) to find the first null and chop your string off appropriately.
新規コントリビューター III
Hi IanH, thank you very much for your comment. It helps much! I changed the wrapper routine and inserted the INDEX(t0dummy_ptr, ACHAR(0)) statement. [fortran] ! get host info FUNCTION mysql_get_host_info (myf) use iso_c_binding IMPLICIT NONE TYPE(myfortran), INTENT(IN) :: myf TYPE(c_ptr) :: c_string_ptr character(kind=c_char, len=512), pointer :: t0dummy_ptr ! type c_char !!!! character(len=:), allocatable :: mysql_get_host_info ! deferred type/shape (f2003) integer :: i
c_string_ptr = c_get_host_info(myf%mysql) call c_f_pointer(c_string_ptr, t0dummy_ptr) ! ,shape(c_string_ptr) i = INDEX(t0dummy_ptr, ACHAR(0)) mysql_get_host_info = t0dummy_ptr(1:(i-1)) END FUNCTION mysql_get_host_info [/fortran] In this way I can work with the result as a normal fortran character. The original library (libmysql.lib -> libmysql.dll) is from the C API delivered with MySQL and delivers a char* in the native C(++)-code, the C-call is: [cpp] const char* c_textdummy; c_textdummy = mysql_get_host_info(MySQLConnection); // or printf("MySQL Connection Info: %s \n", mysql_get_host_info(MySQLConnection)); [/cpp] Nevertheless, the character(c_char) seems to contain still the NULLs from c and if I want to use it in Fortran I have to split them at the NULLs or curous things will happen. Kind regards, Johannes