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

Johannes_Rieke
新規コントリビューター III
1,351件の閲覧回数

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 (http://flibs.cvs.sourceforge.net/viewvc/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')
      USE ISO_C_BINDING
      IMPLICIT NONE
      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 http://software.intel.com/en-us/forums/topic/280611 and http://software.intel.com/en-us/forums/topic/289724 , but unluckily the attachments cannot be downloaded anymore, so that the examples are lost.

Any help will be welcome :-)

Kind regards, Johannes

0 件の賞賛
5 返答(返信)
Johannes_Rieke
新規コントリビューター III
1,351件の閲覧回数
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.
Johannes_Rieke
新規コントリビューター III
1,351件の閲覧回数
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: 127.0.0.1 via TCP/IP Very curious... Johannes
Johannes_Rieke
新規コントリビューター III
1,351件の閲覧回数
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: '127.0.0.1 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
IanH
名誉コントリビューター II
1,351件の閲覧回数
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.
Johannes_Rieke
新規コントリビューター III
1,351件の閲覧回数
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
返信