K I’ll try to provide some info to get this working for you. Now when you say you are working with MySQL Connector, are you using the C connector (6.1) or the C++ connector. If it’s the C++ connector the process should be similar but you may have some clashes between types defined in the C++ connector and UE4.
Also from what I’ve gathered from the code posted you are trying to link dynamically correct? If so then this will be of use to you.
This example will use the MySQL C Connector 6.1 and will be linking dynamically via the DLL and the static import lib (libmysql.dll and libmysql.lib). I should also mention that I compiled the connector myself to avoid any incompatibility problems due to the ancient development tools used to build the binaries distributed by MySQL, although I don’t think this is a problem when dynamic linking (only is static linking is it a problem I think).
Personally, I’ve been linking with the x64 version since my build is targetting windows x64 only but the same will work for x86 as well.
Also note, I’ve implemented this into a module for modularity.
At the root of your project hierarchy, create a folder named ThirdParty. i.e.:
MyProject
[INDENT]Binaries
Build
Config
Content
Intermediate
Saved
Source
ThirdParty
MyProject.sln
MyProject.uproject
[/INDENT]
Within the ThirdParty folder, add the MySQL Connector.C 6.1 folder. You can exclude the bin and docs folder from the connector but the structure within the ThirdParty folder should look like this:
ThirdParty
[INDENT]MySQL Connector.C 6.1
[INDENT]include
lib[/INDENT][/INDENT]
The include folder will have the required header files. The bin folder will have the required libmysql.dll and libmysql.lib.
I’m going to name the module this will be used in MySQLSupport for this example.
In my projects source directory I’ll create the folder structure for the module as follows:
Source
[INDENT]MyProject (my games source directory)
MySQLSupport (my modules source directory)
[INDENT]Public
[INDENT]MySQLSupport.h
Private
MySQLSupport.cpp
MySQLSupportPrivatePCH.h[/INDENT]
MySQLSupport.Build.cs[/INDENT][/INDENT]
I’m sure you already know the process of creating a module and how the source for it should be structured but I’m showing it here for anyone else that comes across this thread seeking help, and the structure matters later on when we are locating the relative path to the ThirdParty folder in the module’s build file.
For the sake of providing complete example, here is an example header file for the module implementation (MySQLSupport.h):
#pragma once
#include "ModuleManager.h"
class IMySQLSupport : public IModuleInterface
{
public:
static inline IMySQLSupport& Get()
{
return FModuleManager::LoadModuleChecked<IMySQLSupport>("MySQLSupport");
}
static inline bool IsAvailable()
{
return FModuleManager::Get().IsModuleLoaded("MySQLSupport");
}
};
and here is the source file for that header (MySQLSupport.cpp):
#include "MySQLSupportPrivatePCH.h"
#include "MySQLSupport.h"
class FMySQLSupport : public IMySQLSupport
{
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
IMPLEMENT_MODULE(FMySQLSupport, MySQLSupport)
void FMySQLSupport::StartupModule()
{
}
void FMySQLSupport::ShutdownModule()
{
}
and of course, here is the private precompiled header for the module (MySQLSupportPrivatePCH.h):
#pragma once
#include "Engine.h"
Short and sweet lol
Now for the build file (MySQLSupport.Build.cs):
using UnrealBuildTool;
using System.IO;
public class MySQLSupport : ModuleRules
{
public MySQLSupport(TargetInfo Target)
{
PublicDependencyModuleNames.AddRange(
new string] {
"Core",
"CoreUObject",
"Engine"
});
string ModulePath = Path.GetDirectoryName(RulesCompiler.GetModuleFilename(this.GetType().Name)); // gets the directory path of this module
string ThirdPartyPath = Path.GetFullPath(Path.Combine(ModulePath, "../../ThirdParty/")); // gets the ThirdParty folder directory path
string MySQLConnectorPath = ThirdPartyPath + "MySQL Connector.C 6.1/"; // gets the MySQL Connector.C 6.1 folder path
string MySQLConnectorLibraryPath = MySQLConnectorPath + "lib/"; // gets the path of the lib folder
string MySQLConnectorIncludePath = MySQLConnectorPath + "include/"; // gets the path of the include folder
string MySQLConnectorImportLibraryName = Path.Combine(MySQLConnectorLibraryPath, "libmysql.lib"); // gets the file path and name of the libmysql.lib static import library
string MySQLConnectorDLLName = Path.Combine(MySQLConnectorLibraryPath, "libmysql.dll"); // gets the file path and name of libmysql.dll
if (!File.Exists(MySQLConnectorImportLibraryName)) // check to ensure the static import lib can be located, or else we'll be in trouble
{
throw new BuildException(string.Format("{0} could not be found.", MySQLConnectorImportLibraryName)); // log an error message explaining what went wrong if not found
}
if (!File.Exists(MySQLConnectorDLLName)) // check to make sure the dll can be located or else we'll be in trouble
{
throw new BuildException(string.Format("{0} could not be found.", MySQLConnectorDLLName)); // log an error message explaining what went wrong if not found
}
PrivateIncludePaths.Add(MySQLConnectorIncludePath); // add the "include" folder to our dependencies. I've chosen PrivateIncludePaths since I hide the mysql headers from external code
PublicLibraryPaths.Add(MySQLConnectorLibraryPath); // add the "lib" folder to our dependencies
PublicAdditionalLibraries.Add(MySQLConnectorImportLibraryName); // add libmysql.lib static import library as a dependency
PublicDelayLoadDLLs.Add(MySQLConnectorDLLName); // add libmysql.dll as a dll
}
}
As you can see, I built up my path strings rather explicitly but it’s for clarity so each path’s use is very clear. So this will handle things on the UBT side but we still need to tell visual studio where to find these files too.
With your project open in Visual Studio, right click on the Project, select Properties and navigate to: Configuration Properties → VC++ Directories and add the following settings:
Include Directories: (add the path to the include folder in MySQL Connector.C 6.1)
Library Directories: (add the path to the lib folder in MySQL Connector.C 6.1)
Now let’s add a class that actually connects to MySQL so we can make sure everything works.
I’ll call this class MySQLTest. It will be a standard c++ class (not derived from UObject) just for simplicity of this example and I am going to add it to my module’s Private directory.
Here is the header file (MySQLTest.h):
#pragma once
#include "AllowWindowsPlatformTypes.h"
#include <winsock2.h>
#include <mysql.h>
#include "HideWindowsPlatformTypes.h"
class MySQLTest
{
public:
MySQLTest();
~MySQLTest();
int32 GetMySQLVersion() const;
private:
MYSQL* conn;
int32 version = -1;
};
Notice how the <winsock2.h> and <mysql.h> are wrapped in the #includes to allow windows platform types. This is important. The compiler will yell at you (and it might even attack you!) if you don’t do this.
and here is the source file (MySQLTest.cpp):
#include "MySQLSupportPrivatePCH.h"
#include "MySQLTest.h"
#pragma comment(lib, "libmysql.lib")
MySQLTest::MySQLTest()
{
conn = mysql_init(NULL);
mysql_real_connect(conn, "localhost", "user1", "supersecretpassword", "somedatabase", 3308, NULL, 0);
version = mysql_get_server_version(conn);
mysql_close(conn);
}
MySQLTest::~MySQLTest()
{
conn = NULL;
}
int32 MySQLTest::GetMySQLVersion() const
{
return version;
}
Nothing too fancy here. This code just simply connects to the specified server (localhost in this case) using the specified user (user1) and password (supersecretpassword) specifying a database instance and a port and queries the database for it’s version number. I specified a default initial value of version as -1 so I can easily identify if there is no setting of the value. The really sexy part here is the variable MYSQL conn*. This is a pointer to our MySQL connection that will be created. I’m not going to get into a MySQL lesson here. This is just a super quick and simple test to make sure everything is working and that we can connect to our database.
Just make sure that the parameters passed to the connect function are valid for your use. For example, I don’t use port 3308.
Other things to note is the #pragma comment(lib, “libmysql.lib”). This handles defining the static import lib in-place.
The last thing you need to do before compiling this is to copy libmysql.lib and libmysql.dll into your project’s bin directory of the target platform (i.e. Binaries/Win64 or Binaries/Win32). This is a gotcha of Unreal Engine 4 at the moment but fingers crossed that this will get fixed in the future.
Oh, and one last thing. Just a minor detail but an important one. Make sure that your project’s target file(s) are specifying the module as an output binary and be sure to add your module to your project’s uproject file.
Now go ahead and compile the code. If you followed along right, you should see everything build nicely.
If you would like to test this out in the editor, just create something that you can spawn in the gameworld that will hold an instance of this class within it and wraps a call to the GetMySQLVersion() function.
One other thing to keep in mind is that if for some reason you happen to regenerate your visual studio project files, the Include Directories and Include Libraries paths you had set in visual studio will have been wiped and need to be set again manually.
Good luck and I hope this clears up problems of anyone trying like hell to get MySQL access within UE4. Oh, and I’ll leave wrapping the MySQL API to you… heh