www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - MySQL connection strange behavior (again...)

reply "miazo" <miazo no.spam.please> writes:
Hello,

I'm facing a strange problem(s) with connecting from D to MySQL
database under Windows XP. I've read almost everything on this
newsgroup concerning database connectivity, I've checked D
libraries written by others, I've read MySQL documentation on its
C API, I searched other sites for similar problems and still I
have no clue what's going on. Perhaps it's something really
trivial?

So, here is what I have done:

- I have MySQL database (version 5.5.20) running on localhost (I
can query it without any problems with its command line tool, so
it's OK).

- I converted libmysql.dll to libmysql.lib with implib.exe tool
with /system option and put resulting libmysql.lib file in
windows\lib directory of DMD compiler.

- The following test code:

	pragma(lib, "libmysql");

	extern (C) {
		alias void MYSQL;
		MYSQL* mysql_init(MYSQL* mysql);
	}

	void main() {
		MYSQL* c = mysql_init(null);
	}

compiles and runs but ends with object.Error: Access Violation
message. The "strange" part is that:

- mysql_init function runs fine - as I understand its purpose, it
just allocates memory for MySQL connection and I can check that
it returns a not-null pointer

- If I put mysql_init in another function like:

	pragma(lib, "libmysql");

	extern (C) {
		alias void MYSQL;
		MYSQL* mysql_init(MYSQL* mysql);
	}

	MYSQL* init() {
		return mysql_init(null);
	}

	void main() {
		MYSQL* c = init();
	}

the program runs without any error message.

My guess is that it's something I'm doing wrong with binding from
C but I have no idea what it can be exactly, as:

- I have come exactly the same way (i.e. C bindings + making of
.lib file) with connecting to SQLite, Postgres and via ODBC and I
have not encounter such problems (I can connect and execute
queries).

- I can actually connect to MySQL and execute queries - the above
example is simplified. But as I work with MySQL database I see
more and more strange behavior, for instance: I use a variable to
store number of fields in a result (mysql_num_fields function
gives me that) and when I later want to get that number I see
something like 18454345 (but earlier it was just: 2 fields). So
it looks like something have corrupted the memory where I put my
data? Can it be GC (but I have no such problems with other DB
engines)? Or is it MySQL library? The most annoying part is that
very often I can't reproduce the problem - simply changing the
order of two commands in a program can fix or brake it.

- There was a known problem with unsigned long in MySQL bindings
but what I'm using is just uint.

- Maybe it has something to do with the database encodings? But
my database uses utf-8 and I set it to utf-8 for session just
after opening a new connection (with mysql_set_character_set
function).

Thank you for your help and any ideas that can help me to debug
it further.

PS. I am aware of the fact that there are (were?) efforts to make
a common database library for D; nonetheless I just wanted to
learn D and as I have database background writing that kind of
library seemed most familiar to me.
Feb 22 2012
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 22 February 2012 at 12:06:42 UTC, miazo wrote:
 	extern (C) {

This should be extern(System), not extern(C). My guess is that's causing most your problems.
Feb 22 2012
prev sibling next sibling parent "miazo" <miazo no.spam.please> writes:
Thank you for that suggestion but I have tried it before - 
changing extern (C) to extern (Windows) gives me a linker error:

Error 42: Symbol Undefined _mysql_init 4

As I wrote, I have libmysql.lib in a proper DMD folder and I can 
see that _mysql_init function is defined inside. I have tried two 
versions of libmysql.lib that I could create: the one made from 
original libmysql.lib from MySQL installation converted with 
coffimplib utility, and the other one made from libmysql.dll with 
implib utility. Both versions compile if I stay with extern (C) 
instead of extern (Windows). I was wondering if this is really 
necessary? Sqlite bindings, for example, use extern (C) without 
problems. If it is, how do I get rid of that linker error?

On the other hand, I have found this bug: 
http://d.puremagic.com/issues/show_bug.cgi?id=3342 which is 
marked as FIXED. But as I read the full description linked there 
I have that feeling that this is what I observe when I work with 
MySQL database (but why it is not the case with Sqlite or 
Postgres?). Can it be verified somehow or is there some 
workaround?
Feb 22 2012
prev sibling next sibling parent "Mars" <- -.-> writes:
He said System, as in literally System, not System as in your 
System. Your example works fine for me with that.
Feb 22 2012
prev sibling next sibling parent "miazo" <miazo no.spam.please> writes:
Well, on http://dlang.org/attribute.html I can read that "System 
is the same as Windows on Windows platforms, and C on other 
platforms".

BTW, under which Windows version did you check?
Feb 22 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 22 February 2012 at 17:02:01 UTC, miazo wrote:
 Error 42: Symbol Undefined _mysql_init 4
 libmysql.dll with implib utility.

I think the /s switch is needed on that one when doing the mysql libraries on implib. /s changes what's done with the _ in the front. I've done this before but don't remember exactly what I did though.
Feb 22 2012
prev sibling next sibling parent "miazo" <miazo no.spam.please> writes:
Yes, /s or /system is a switch that appends _ in front of names 
from a .dll file. This is exactly how I've used implib.
Feb 22 2012
prev sibling next sibling parent "miazo" <miazo no.spam.please> writes:
Problem solved. :-)

I found that it was  4 suffix that was missing. With a 
libmysql.def file as below:

LIBRARY libmysql
EXETYPE NT
SUBSYSTEM WINDOWS
EXPORTS
	_mysql_init 4 = mysql_init

I was able to generate working libmysql.lib file with implib 
(with /system switch).

That, with changing from extern (C) to extern (System), removed 
the problematic issue.

Thank you for all your hints!
Feb 22 2012
prev sibling next sibling parent "Kapps" <opantm2+spam gmail.com> writes:
On Wednesday, 22 February 2012 at 21:18:32 UTC, miazo wrote:
 Problem solved. :-)

 I found that it was  4 suffix that was missing. With a 
 libmysql.def file as below:

 LIBRARY libmysql
 EXETYPE NT
 SUBSYSTEM WINDOWS
 EXPORTS
 	_mysql_init 4 = mysql_init

 I was able to generate working libmysql.lib file with implib 
 (with /system switch).

 That, with changing from extern (C) to extern (System), removed 
 the problematic issue.

 Thank you for all your hints!

You shouldn't have to manually create a .def file. Try using coffimplib (I think it's bundled with dmc?) instead of implib and use it on libmysql.lib (coffimplib libmysql.lib _libmysql.lib, back up the original libmysql.lib, replace the original with the generated _libmysql.lib, and then link to it). Then create your headers with extern(System). It seems that adding it manually into the .def file is working for you, but it's a lot more effort than needed.
Feb 22 2012
prev sibling parent "miazo" <miazo no.spam.please> writes:
You are right, coffimplib with -e switch does it.
Feb 23 2012