Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29273 Discussions

VS2008 using mysql.f90 and trying to link libmysql.lib to a Fortran program

Matthias_H_2
Beginner
3,138 Views

Hi all,

I am having a problem linking the libmysql.lib and mysqlclient.lib to my Fortran project. I am using the mysql.f90 by Daniel Kraft. I am further using the Intel 11.1 Fortran compiler in VS2008. The errors I am getting are all of this sort:

error LNK2019: unresolved external symbol _mysql_init referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_CONNECT

It seems to be missing mysql_init, mysql_close, mysql_real_connect, mysql_real_querry, and so on

I did check with the lib command the contents of the library libmysql.lib and they refer to the libmysql.dll. I did check their content and all the references I am missing are in there. From what I understand that should be fine as this dll is used when executing the program. However, for some reason, this does not work when linking.

I did add to the properties page of the project under Linker -> general the path to the libraries and under -> input the names of the two libraries. I checked if its looking for the libs through changing the name of one lib, and then VS complains that it cannot find the library its looking for. So it should be looking at those two libs, I think.

Any ideas how to fix this problem.

Some more infos, I am running Win7 enterprise (64Bit) but the compiler is using the IA32 stuff, so that should be 32 bit code. I downloaded the mysql libs from the mysql site.

Any idea what the problem could be?

Kind regards, Matthias

0 Kudos
22 Replies
Steven_L_Intel1
Employee
2,698 Views
Keep in mind that capitalization and punctuation matters when the linker is looking for names. Are the names EXACTLY as shown in the library, or do they differ in some small way? Please put the .lib in a ZIP file and attach it here, or point to where it can be found on the net, and I'll take a look.
0 Kudos
Matthias_H_2
Beginner
2,698 Views
Hi Steve, Thanks for the quick answer. I downloaded the files from http://dev.mysql.com/downloads/connector/c/ and then downloaded mysql-connector-c-noinstall-6.0.2-win32.zip. I extracted the libraries and put them in the appropriate path so visual studio would find them. (its attached) I used dumpbin to look at the contents of the dll and yes there is a small difference The calls in mysql.f90 ask for e.g. mysql_init, the linker says _mysql_init is not found and in the dll there is a mysql_init@4. I thought that would not matter, but obviously it does. I have to admit I am new to this. Anyway what do I have to do to resolve this issue. Many thanks in advance. Matthias
0 Kudos
Steven_L_Intel1
Employee
2,698 Views
Yes, it does matter. The names with @4, etc., at the end are STDCALL routines that use a different calling convention than Intel Fortran uses as a default. There is also a leading underscore in the name which is important. You can fix the linking problems by adding directives that look like this: !DEC$ ATTRIBUTES STDCALL, REFERENCE :: mysql_connect for each of the routines you are calling. You may want to put these in an INCLUDE file and include them. This won't solve all your problems, though. You need to figure out, for each argument of each routine you are calling, whether the argument is passed by value or by reference. The lines I suggested above will pass by reference by default, which would match a C declaration of *something, but I expect there are routines that take things by value. You can enclose such arguments in %VAL() to make them passed by value if that's the case. What you REALLY should do is write a set of interface blocks for these routines and specify the datatypes and passing mechanism for each argument. That's a lot of work but will save you hassle and errors later.
0 Kudos
mecej4
Honored Contributor III
2,698 Views
The library libmysql.lib (included in your zip file) appears to be intended to be called with the STDCALL convention, since the routine names have been decorated with @nn-type suffixes, where nn stands for the number of bytes in the argument list. Intel Fortran uses a different default calling convention, but a compiler switch allows STDCALL to be used instead. You will need to ascertain the prescribed usage of the Mysql library and, possibly, read the Mixed-Language-Programming chapter of the Intel Fortran User Guide.
0 Kudos
Johannes_Rieke
New Contributor III
2,698 Views
Hi Matthias, I'm using the same mysql.f90 by Daniel Kraft but modified it in some points. I've attached my version of it. In my VS2010 Project I've the following settings: Fortran --> General --> Addtional include directories: D:\Programme\mysql-5.5.27-winx64\include Linker --> General --> Additional library directories: D:\Programme\mysql-5.5.27-winx64\lib\ Linker --> Input --> Additional Dependencies: D:\Programme\mysql-5.5.27-winx64\lib\libmysql.lib Please note, that I'm not using the connectors but the full mysql installation (zip). I use Win7 x64 too, but I compile in x64 also. Calling convention is default of ifort 12.1. A call in Fortran to the MySQL_binding looks like: [fortran] ! *** Connect to data base pwd = ''//C_NULL_CHAR db = ''//C_NULL_CHAR MySQLConnect = myfortran_connect(MySQL_DB(1), MySQL_DB(2), pwd, db) call mysql_select_db (MySQLConnect, MySQL_DB(3)) ! ! *** Search table and check data types MySQL_result = myfortran_query_get(MySQLConnect, 'DESCRIBE '//trim(MySQL_table_name)) imaxrows = myfortran_num_rows(MySQL_result) allocate(data_type(imaxrows)) do i = 1, imaxrows l0success = myfortran_fetch_row(MySQL_result, MySQL_row) if(l0success)then indexmax = MySQL_row%num_fields data_type(i) = myfortran_get_field(MySQL_row, 2) else write(*,'("!!! Error in ",a,"! Could not get results of table ",a)') csubr, trim(MySQL_table_name) write(*,'(" Abort with ENTER")') read(*,*) stop end if end do [/fortran] It works quite robust and good in Windows with Intel (12.1) and Linux with GCC (4.5 & 4.6.3). Hope that helps. Kind regards, Johannes
0 Kudos
JVanB
Valued Contributor II
2,698 Views
Having code that works in both ifort and gfortran indicates that you are only attempting to make it work in 64-bit mode. Try the same thing in 32-bit mode and nothing can work because gfortran uses the BIND attribute + a one-line directive to interface with STDCALL functions whereas ifort uses an archaic mechanism they inherited from Microsoft which is totally incompatible. Intel will likely never fix their compiler to work with C interoperability because what they have works already and they may even have licensed their interfaces to other vendors like PGI. You may want to get everything working and tested in 64-bit mode and only later convert to the !DEC$ ATTRIBUTES style interfaces for use on 32-bit mode.
0 Kudos
Steven_L_Intel1
Employee
2,698 Views
Never say never, RO. There's nothing stopping us from allowing STDCALL with BIND(C) and it is something I have proposed to the developers. As for PGI, they have not licensed anything from us and what Windows API modules they have they created on their own. Last I tried their compiler, it was not compatible with ours in this regard.
0 Kudos
JohnNichols
Valued Contributor III
2,697 Views
I tried this software till I was blue in the teeth. Bite the bullet and buy the qe software from Germany it is quick easy and painless to use. I connects to anything with a minimum of fuss. I have no shares in the company and hopefully by this time our accountants have actually finally paid for it. I used it to run 132 million data sets into SQL Server without a hitch.
0 Kudos
Matthias_H_2
Beginner
2,698 Views
Hi all, Many thanks for all the suggestions. I have tried several things none of which worked so far, unfortunately. As suggested by Steven I included the !DEC$ ATTRIBUTES STDCALL, REFERENCE :: but that did not work, it is still missing the references: error LNK2019: unresolved external symbol _mysql_init referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_CONNECT mysql.obj _mysql_real_connect referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_CONNECT _mysql_close referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_DISCONNECT _mysql_real_query referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_QUERY_DO _mysql_store_result referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_QUERY_GET _mysql_free_result referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FREE_RESULT _mysql_num_rows referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_NUM_ROWS _mysql_fetch_row referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FETCH_ROW _mysql_num_fields referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FETCH_ROW _mysql_fetch_lengths referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FETCH_ROW _mysql_error referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_ERROR Those are the routines that are defined in the interface blocks in the package mysql.f90 (is attached, looks much like the one that was posted by Johannes later. The attached file includes only the DEC for the mysql_init for testing) I am not sure where I should add the compiler directive. I have tried it at the beginning of the myfortran_binding module as well as in the main program, it does not make a difference. I have also downloaded the full version of mysql and taken the libraries from there (as suggested by Johannes) also no success. I assume (ok I have the feeling) I am still doing something wrong with the !DEC statement. Is there any command I have to give when compiling so that it recognizes the directives !DEC commands? Many thanks for additional help in advance, Matthias
0 Kudos
Steven_L_Intel1
Employee
2,698 Views
Thanks for attaching your source. It helps. You, reasonably so, have interface blocks for the mysql routines. You also used BIND(C) with NAME=. Ordinarily that would be good, but as discussed above, this doesn't work when calling STDCALL routines in Intel Fortran. So what you have to do is remove the BIND clause and then add, after each SUBROUTINE or FUNCTION line inside the INTERFACE, a line that looks like this: !DEC$ ATTRIBUTES STDCALL,REFERENCE,DECORATE,ALIAS:"mysql_connect" :: c_connect You would change the mysql_connect and c_connect as needed for each of the procedures. I have attached a modified source where I did this for a few of the routines so you can see how it is done. The ALIAS is needed because you call these routines by something other than their external name, and DECORATE takes care of adding the name decoration.
0 Kudos
Matthias_H_2
Beginner
2,698 Views
Dear Steve, Many thanks again for your help. Unfortunately it still does not link, although I am one step further thanks to your help. When linking it now complains about not finding _mysql_init@8 referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_CONNECT _mysql_connect@52 referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_CONNECT _mysql_real_query@16 referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_QUERY_DO _mysql_store_result@8 referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_QUERY_GET _mysql_fetch_row@8 referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FETCH_ROW _mysql_fetch_lengths@8 referenced in function MYFORTRAN_BINDING_mp_MYFORTRAN_FETCH_ROW _mysql_error@8 referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_ERROR so it did find _mysql_close referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_DISCONNECT _mysql_free_result referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FREE_RESULT _mysql_num_fields referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_FETCH_ROW _mysql_num_rows referenced in function _MYFORTRAN_BINDING_mp_MYFORTRAN_NUM_ROWS two of which are functions and two of which are subroutines. I tried to find out what the @n means in the module names, but I could not. Maybe you can help me out with this one. I guess I have the wrong library now, but in order to find the correct one it would be great to know what the @n means. The other thing I do not understand is why Johannes reported that his version of mysql-f90 (including the BIND statement) works with VS2010 and Intel Fortran 12.1. Was there a major change between version 11.1 and 12.1. Kind regards Matthias
0 Kudos
Steven_L_Intel1
Employee
2,698 Views
The @n means it is a STDCALL routine that neewd n bytes pooped off the stack on exit, based on the number of arguments. It has nothing to do with modules. I'd have to compare your declarations with the ones in the C header to see what is wrong. Probably a wrong number of arguments.
0 Kudos
Johannes_Rieke
New Contributor III
2,698 Views
Hi Matthias, If I understand repeat offender right the difference is in 32bit vs. 64bit. Ifort seems to use different calling conventions as default for 32bit and 64bit. The 32bit calling convention seems to be a bit tricky with calling C/C++ and requires the !dec$ directives. Steve correct me please, if I'm wrong... In addition I use not the connectors from "mysql-connector-c-noinstall-6.0.2-win32" but the libraries which are provided in "mysql-5.5.27-winx64.zip". First I tested the connector (64bits) but could not link. With "mysql-5.5.27-winx64.zip" I had no problems... Maybe you can test the "mysql-5.5.27-winx32.zip" libraries? Maybe ArjenMarkus could help on this? He is maintaining the flibs? Best regards, Johannes
0 Kudos
Anthony_Richards
New Contributor I
2,698 Views
I note that the code includes 23 l0success = myfortran_fetch_row(MySQL_result, MySQL_row) 24 25 if(l0success)then 26 27 indexmax = MySQL_row%num_fields So my question to Steve is, what happens to the name decoration when compiled for 64-bit if the arguments MySQL_result, MySQL_row are 8-byte pointers/adresses? Should you get @16rather than @8?
0 Kudos
Arjen_Markus
Honored Contributor II
2,698 Views
With 64-bits systems there is no STDCALL convention IIUIC. As that is responsible for the @4 etc decoration, the question you raised does not actually arise.
0 Kudos
Johannes_Rieke
New Contributor III
2,698 Views
Hi Matthias, Sorry, I've seen too late that you tested the "mysql-5.5.27-winx32.zip" version already. Have you noticed, that there is a special version for VS(2005): "mysql-connector-c-noinstall-6.0.2-win32-vs2005.zip" I don't know where the differences are, but maybe it is something with calling convention? Only a guess... Is it possible for you to switch to x64? It seems to be the easiest solution? I've thought also to use the MySQL Fortran interface by QT Software mentioned above, but my software have to run also on Linux and the QT solution is not available for Linux currently. Kind regards, Johannes
0 Kudos
Steven_L_Intel1
Employee
2,698 Views
The @n convention and STDCALL does not exist on x64, as noted. The compiler accepts the STDCALL attribute and will apply the other changes (downcase name, pass by value) on x64. I think that's going off on a tangent. I think I see what the problem is. Let's look at mysql_init for an example. The interface block for this is: FUNCTION c_init_mysql (mysql) !DEC$ ATTRIBUTES STDCALL,REFERENCE,DECORATRE,ALIAS:"mysql_init" :: c_init_mysql USE ISO_C_BINDING IMPLICIT NONE TYPE(C_PTR) :: c_init_mysql TYPE(C_PTR), VALUE :: mysql END FUNCTION c_init_mysql Note that the function returns an object of TYPE(C_PTR). In C, the function just returns a pointer which is placed in a register. But in Fortran, without BIND(C), any function returning a derived type passes a "hidden argument" for returning the value. A solution for this is to change the declaration of the return value to: integer(C_INTPTR_T) :: c_init_mysql Then when the result is used if you wanted to make it a C_PTR you'd have to do something like: TRANSFER(retval, C_NULL_PTR) (this is a function call) to convert the integer pointer to a C_PTR, and then presumably you'd use it in as call to C_F_POINTER.
0 Kudos
Matthias_H_2
Beginner
2,698 Views
Hi all, I did several checks and reprogramming all with no success this morning. I finally tried to compile the stuff using the 64bit version and it complied. I used the equivalent libraries from the mysql version 5.0.95 that I am running , but only the 64 bit ones instead of the 32 bit ones. I also used the mysql.f90 version provide by Johannes in this discussion. It complies fine. I have tried to connect to the data base using a small program just trying to connect to the database program Read_database use mod_MySQLfortran_binding USE ISO_C_BINDING implicit none TYPE (myfortran) :: MySQLConnect ! Variables ! Body of Read_database ! *** Connect to data base ! the *** are placeholders MySQLConnect = myfortran_connect( 'localhost','***',’****’,'*****' ) End program Read_database But I get an error: cannot connect to localhost. Took me quite some while to figure out that instead of localhost I have to give it 127.0.0.1 instead. All my other programs (written in c++) use localhost instead. Now I can connect to the database. I would like to thank everyone who helped so much in solving this problem. Many thanks Matthias
0 Kudos
Steven_L_Intel1
Employee
2,698 Views
My guess is that it wants NUL-terminated strings. So use 'localhost'C, etc.
0 Kudos
Matthias_H_2
Beginner
2,599 Views
Hi Steve, their is a NUL-terminated string in the call, so it cannot be this, that is at least what I think. Matthias
0 Kudos
Reply