These two example programs should work without any changes on a Linux or FreeBSD system. For other operating systems, minor changes are needed, mostly with file paths. These examples are designed to give enough details for you to understand the problem, without the clutter that is a necessary part of a real application. The first example is very straightforward. The second example is a little more advanced with some error checking. The first is followed by a command-line entry for compiling the program. The second is followed by a GNUmake file that may be used for compiling instead.
Example 1
test1_libmysqld.c
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "mysql.h" MYSQL *mysql; MYSQL_RES *results; MYSQL_ROW record; static char *server_options[] = \ { "mysql_test", "--defaults-file=my.cnf", NULL }; int num_elements = (sizeof(server_options) / sizeof(char *)) - 1; static char *server_groups[] = { "libmysqld_server", "libmysqld_client", NULL }; int main(void) { mysql_library_init(num_elements, server_options, server_groups); mysql = mysql_init(NULL); mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client"); mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); mysql_real_connect(mysql, NULL,NULL,NULL, "database1", 0,NULL,0); mysql_query(mysql, "SELECT column1, column2 FROM table1"); results = mysql_store_result(mysql); while((record = mysql_fetch_row(results))) { printf("%s - %s \n", record[0], record[1]); } mysql_free_result(results); mysql_close(mysql); mysql_library_end(); return 0; }
Here is the command line for compiling the above program:
gcc test1_libmysqld.c -o test1_libmysqld -lz \ `/usr/local/mysql/bin/mysql_config --include --libmysqld-libs`
Example 2
To try out the example, create an
test2_libmysqld
directory at the same level
as the MySQL source directory. Save the
test2_libmysqld.c
source and the
GNUmakefile
in the directory, and run GNU
make
from inside the
test2_libmysqld
directory.
test2_libmysqld.c
/* * A simple example client, using the embedded MySQL server library */ #include <mysql.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> MYSQL *db_connect(const char *dbname); void db_disconnect(MYSQL *db); void db_do_query(MYSQL *db, const char *query); const char *server_groups[] = { "test2_libmysqld_SERVER", "embedded", "server", NULL }; int main(int argc, char **argv) { MYSQL *one, *two; /* mysql_library_init() must be called before any other mysql * functions. * * You can use mysql_library_init(0, NULL, NULL), and it * initializes the server using groups = { * "server", "embedded", NULL * }. * * In your $HOME/.my.cnf file, you probably want to put: [test2_libmysqld_SERVER] language = /path/to/source/of/mysql/sql/share/english * You could, of course, modify argc and argv before passing * them to this function. Or you could create new ones in any * way you like. But all of the arguments in argv (except for * argv[0], which is the program name) should be valid options * for the MySQL server. * * If you link this client against the normal mysqlclient * library, this function is just a stub that does nothing. */ mysql_library_init(argc, argv, (char **)server_groups); one = db_connect("test"); two = db_connect(NULL); db_do_query(one, "SHOW TABLE STATUS"); db_do_query(two, "SHOW DATABASES"); mysql_close(two); mysql_close(one); /* This must be called after all other mysql functions */ mysql_library_end(); exit(EXIT_SUCCESS); } static void die(MYSQL *db, char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); (void)putc('\n', stderr); if (db) db_disconnect(db); exit(EXIT_FAILURE); } MYSQL * db_connect(const char *dbname) { MYSQL *db = mysql_init(NULL); if (!db) die(db, "mysql_init failed: no memory"); /* * Notice that the client and server use separate group names. * This is critical, because the server does not accept the * client's options, and vice versa. */ mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test2_libmysqld_CLIENT"); if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0)) die(db, "mysql_real_connect failed: %s", mysql_error(db)); return db; } void db_disconnect(MYSQL *db) { mysql_close(db); } void db_do_query(MYSQL *db, const char *query) { if (mysql_query(db, query) != 0) goto err; if (mysql_field_count(db) > 0) { MYSQL_RES *res; MYSQL_ROW row, end_row; int num_fields; if (!(res = mysql_store_result(db))) goto err; num_fields = mysql_num_fields(res); while ((row = mysql_fetch_row(res))) { (void)fputs(">> ", stdout); for (end_row = row + num_fields; row < end_row; ++row) (void)printf("%s\t", row ? (char*)*row : "NULL"); (void)fputc('\n', stdout); } (void)fputc('\n', stdout); mysql_free_result(res); } else (void)printf("Affected rows: %lld\n", mysql_affected_rows(db)); return; err: die(db, "db_do_query failed: %s [%s]", mysql_error(db), query); }
GNUmakefile
# This assumes the MySQL software is installed in /usr/local/mysql inc := /usr/local/mysql/include/mysql lib := /usr/local/mysql/lib # If you have not installed the MySQL software yet, try this instead #inc := $(HOME)/mysql-5.1/include #lib := $(HOME)/mysql-5.1/libmysqld CC := gcc CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT CFLAGS := -g -W -Wall LDFLAGS := -static # You can change -lmysqld to -lmysqlclient to use the # client/server library LDLIBS = -L$(lib) -lmysqld -lz -lm -ldl -lcrypt ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null)) # FreeBSD LDFLAGS += -pthread else # Assume Linux LDLIBS += -lpthread endif # This works for simple one-file test programs sources := $(wildcard *.c) objects := $(patsubst %c,%o,$(sources)) targets := $(basename $(sources)) all: $(targets) clean: rm -f $(targets) $(objects) *.core
User Comments
I'm currently working on embedding this into a dll that is compiled with Visual C++. I found the following useful to make this compile.
It is necessary to ensure winsock.h is included before mysql.h. This is because SOCKET is defined in winsock.h and is used by mysql_com.h and mysql.h includes mysql_com.h.
I noticed that winsock.h is included in mysql.h but is wrapped inside a #ifdef. I suppose another alternate would be to figure out why this isn't being entered and resolve it.
Example,
#ifdef __LCC__
#include <winsock.h> /* For windows */
#endif
As we can see, if __LCC__ were defined there would be no reason to include winsock.h. If this is a bug someone should report it.
Also, when compiling this for an MFC application, I found it necessary to turn off/disable precompiled headers. For some reason, including winsock.h wasn't being accepted when called after #include stdafx.h. After disabling precompiled headers the code compiled; hmmm maybe that is another bug.
One reason for my post is a search on the internet suggested others were unable to compile this for the same reason I was unable.
For the simple embedded server example code in documents, there is a bug in the Makefile. You have to put "-lstdc++" to gcc command line to solve the problem, or after you type make, you'll get a lot of "undefined reference" errors.
On Windows, I had trouble getting the mysql embedded server to go passed mysql_server_init() function. After many hours of fiddling with the settings, I discovered that if you have the mysql-service running in the background (usually mysqld-nt.exe) the call to mysql_server_init() will fail! I have disabled the service from starting up... I don't know if this is a bug or a sharing violation with mysql service (seeing as that's also an embedded server!?) or I need to take some extra steps before running my exe, either way, killing the mysql service isn't the ideal fix.
I can't speak for later releases yet, but for 4.1 here
are some hard won tips:
the embedded server still reads c:\my.cnf and must find
enough initialization there under the keys you've specified
(ie [server]) to make it happy. It will need to find at
least the datadir and language dir. This default behavior
makes it hard to develop a really standalone embedded
application - it really wants to parasitize a regular mysql
installation.
The parser for my.cnf requires path names with
forward slashes even on windows.
Any failures in the initialization process cause a silent
and immediate exit. I only figured out what was going on
by downloading the source and building a complete debugging
environment.
After many try-n-errors, I made it to embed MySQL with a scripting language (http://www.zegraph.com/z-script/mysql-reference.html). You can find the source code at http://www.zegraph.com/z-script/src/mysql.cpp. Here are a few points that I think may be helpful for those having problems:
1. Use the same compiling flags for libary and program.
I had problem with linking the distribulted library by VC6++. So I compiled static libraries acoording to flags in distributed project files. For libmysald, I used
WIN32,NDEBUG,_WINDOWS,SIGNAL_WITH_VIO_CLOSE,HAVE_DLOPEN,EMBEDDED_LIBRARY,HAVE_INNOBASE_DB,DBUG_OFF,__WIN__
And for the program I used
WIN32,NDEBUG,_CONSOLE,_MBCS,_WINDOWS,SIGNAL_WITH_VIO_CLOSE,HAVE_DLOPEN,EMBEDDED_LIBRARY,HAVE_INNOBASE_DB,DBUG_OFF,__WIN__
2) Use similar arguments as follows to initialize the server
char *server_groups[] = { "client", "server", 0 };
char *server_options[] = { "mysql_embedded", "--defaults-file=e:\\my.ini"};
And in "my.ini" groups of [client] and [server] must exist, somting like:
[client]
default-character-set=utf8
[server]
basedir=e:/db
datadir=e:/db/data
default-character-set=utf8
3) Contents in the distributed share directory should be copied to basedir for MySQL to find charactersets and etc.
Add your own comment.