Enabling C++14?/using Sol2 Lua wrapper?

EDIT : Solution for using Sol2 with UE4 posted further down
Click here to get to the post : Enabling C++14?/using Sol2 Lua wrapper? - C++ - Unreal Engine Forums

**Old post : **

I’m trying to make LuaJit and Sol2, a lua wrapper, work with Unreal 4 (mostly because i love its speed and syntax).
While LuaJit is behaving fine i have some trouble with Sol2: When trying to build my project i get tons of error messages,like:



warning C4628: digraphs not supported with -Ze. Character sequence '<:' not interpreted as alternate token for ''
error C4002: too many actual parameters for macro 'check'
error C2988: unrecognizable template declaration/definition
error C2059: syntax error: '<end Parse>'
error C2334: unexpected token(s) preceding '{'; skipping apparent function body


There is nothing wrong with the Sol2 files, they’re working perfectly fine when used by a non-UE4 project. According to the Sol2 documentation these error messages are produced by the sol2 files most likely because C++14 isn’t enabled in UE4.
How do i enable C++14 with UE4 projects in VS2015? Or did anyone else manage to make Sol2 work with UE4?

I already found a possibe answer here

but none of my EpicGames or UnrealProjects folders has any “Engine/Source/Programs/UnrealBuildTool” subfolder nor a “ToolChain.cs”-file.

Any help is appreciated. :slight_smile:

did you download the source version from github?

You mean source version of Sol2? Yes.
Or do you mean from UE4? I just downloaded it. What do i have to do now?

no clue, but the “but none of my EpicGames or UnrealProjects folders has any “Engine/Source/Programs/UnrealBuildTool” subfolder nor a “ToolChain.cs”-file.” issue will likely be resolved with the source version.

Anyone using digraphs in modern C++ is not serving their users right.
Digraphs were invented to support C++ on EBCDIC style encoding systems, and are a very bad idea in modern code.
You could run a script that replaces the digraphs with their appropriate real characters.

If it also uses other features that Unreal hasn’t turned on, then you’ll have to set up your projects to separately compile this code, and then use a link compatible interface to talk to it.

Well, i built the source version and there was still no ToolChain.cs file, but i found a “VCToolChain.cs” in the UnrealBuildTool/Windows subfolder, i guess they changed it since back when that linked post was written… but changing anything there didn’t help either, still no C++14.

I read through the source code of Sol2 and it’s not really using digraphs, the compiler just thinks that its using diagraphs because of lines like

struct tie_size<::sol::tie_t<Tn…>> : ::std::tuple_size<::std::tuple<Tn…>> { };

But these warnings aren’t really my problem, i can remove the “::” and it’s fine and dandy, it’s the other errors i worry about, hence why i asked how to use C++14 with UE4 since it’s stated in the Sol2 manual that C++14 is required.

Well, my hope was that when i have C++14 active in UE4 that all the neccessary features are available. Do you have any link for examples or tutorials how such separate compiling and then interface-linking could be done?

EDIT : It seems like these errors occur because UE4 uses tons of macros to redefine , some of which being “#define check(”, and sol2 is using “check()” aswell, so when using sol2 in a UE4 it conflicts with UE4s check macros.
I fixed that by undefining and redefining UE4s check macros after the sol.hpp inclusion


#undef check
#include "sol.hpp"
#define check(expr)             { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } }

That gets rid of all the errors, only a few new errors are thrown:


2>\sol2\Includes\sol.hpp(1028):` error C4583: 'sol::storage_t&lt;T&gt;::value_': destructor is not implicitly called

and


2>\sol2\Includes\sol.hpp(1028): error C4583: 'sol::storage_t<T>::value_': destructor is not implicitly called

which come from this piece of code:



 template <class T>
 union storage_t
 {
   unsigned char dummy_;
   T value_;
 
   constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};
 
   template <class... Args>
   constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
 
   ~storage_t(){}
 };


Does UE4 have any special convention for using constructors/destructors in third party code?

I wish I knew of a great tutorial, because that’s the #1 problem when integrating third party code into large systems in general.
Now, if what you want out of Sol is a C++ programming interface, there is no way to wrap that up in a link-compatible DLL, because C++ does not have a simple, well-defined ABI :frowning:
If that’s not a problem for you, then the general way you go about this is write a header with C-style functions and structures for the functions you want. Very important: Do not include the C++ headers of the underlying library in this header; define your own structs for the data structures you need!
Then, write a simple source file that implements those C-style functions on top of the C++ library you have, and export those functions.
Finally, build the entire thing (C++ library + C functions using the library) as a DLL/.so. When you link against it in another project, include your custom C-style header, but not the C++ headers.

So essentially what you mean i should do is something like this?

Which is

  1. create an “solInterface.h” C-file that defines certain functions like
    int sol_getValueOfLuaTableEntry(char* tablename, int index)

  2. create an “solInterface.c” C-source file that implements these functions in C and #includes the sol.hpp C++ files

  3. compile both c interface files and the sol2 C++ hpp it as a dll

  4. include the solInterface.h C-file in UE4

Correct?

Correct! But then the question is whether Sol really gives you much value on top of the base Lua interface, which is already C linkable.

Well, the reason i use Sol2 is because i won’t have to worry about the Lua stack and i find the syntax alot more comfortable than plain C Lua.

My plan would be to

  1. only have C-functions in the header
  2. have those C-functions inside a extern “C” { <function_implementations> }, which then call corresponding C++14 functions in the same source file, basically something like this:


//===================interface.h===================================
//C-code:

int c_getValue(char* table); //gets called by UE4

//===================interface.cpp=================================
#include "interface.h"

//C++11/14 code
 int cpp_getValue(char* table) {
     int x = <get lua state and read that Lua table value>
     //Do C++11/14 stuff...
     return x;
 }

//C code
extern "C" {    
 int c_getValue(char* table) {
    return cpp_getValue(table); //Calls above C++11/14 method
 }
}



Of course i’d need tons of interface methods for all the different ways i’d want to access Lua but i wouldn’t mind that… i’d still prefer that over plain C Lua :wink:

So essentially an entire “read data from lua database” would go
UE4 calls C interface -> C interface calls C++11/14 function -> C++14 function calls Sol2 Lua and gets C++14 data back, converts to C compatible data and return to C function -> C function returns data to UE4 -> UE4 is happy.
I thought that would work since UE4 would only handle C/C++11 data, which C returns, and with the C -> C++14 interface it would provide the C++14 advantages that sol2 can return from lua (like tuples, custom usertypes, etc) which plain C can’t read.

What do you think?

I haven’t done such a dll interface before, so i’m curious : Do i have to use a C interface/is a C interface strongly recommended?
Or would it be enough if the interface header used C++11 function declarations (aka UE4 compatible) and only the interface source file (.cpp) would use C++14-related stuff (aka Sol2)?
I’m asking because a C++11 interface instead of a C interface would remove one translation/data transfer step in each direction, from
UE4-> C call -> C++ call->Sol2 (C++14) -> C++ return -> C return-> UE4 (6 steps)
to
UE4-> C++ call -> Sol2 (C++14) -> C++ return -> UE4 (4 steps)
and would require less functions to write, since i wouldn’t need the C functions.

That is generally what works best, because it has the least chance of colliding with something else.
If you use C++, then something as simple as upgrading the compiler version may suddenly break cross-compatibility.
If you use the STL, then all bets are off, because it includes all kinds of version-specific dependencies into the binary interface.

A trade-off that stays mostly compatible, if you want to use C++, is to use pure abstract base classes. This ends up only having a dependency on the layout of vtables, which doesn’t change as much these days.



class MyThing {
public:
  virtual void doStuff() = 0;
  virtual int getTheValue() = 0;
  virtual void dispose() = 0;
protected:
  virtual ~MyThing() {}
};

extern MyThing * makeAThing();


If you export makeAThing() from the DLL, you can use it from another EXE/DLL. In the implementation, you will declare, instantiate, and return, some subclass of MyThing, that can use as much STL and C++14 you want, because it’s not a binary dependency in the linkable interface.
(Note the dispose() function, and making the destructor protected! Users will have to call dispose() instead of delete, which makes sure that “new” and “delete” are implemented in the same DLL, so they don’t mis-match across versions.)

Alright, i think i’ll choose the safe C interface-way then. I think data safety/compatibilty is more important for an interface than a few less lines to type for the lazy interface programmer. :wink:

Thank you so very, very much for your help! I really appreciate it. :slight_smile:

**SOLUTION / Ok, some good news : **
No interface needed anymore, i’ve analyzed a few things that made UE4 incompatible with sol2, let the developer know it and it seems that the new Sol2 release is UE4 compatible (at least when using Visual Studio 2015, not sure about other programs).

There is only one thing you need to pay attention to :
When including the “sol.hpp” in an UE4 project you need to wrap it around in an #undef and #define shell for the check() macro, like this:



#undef check
#include "sol.hpp"
#if DO_CHECK
	#define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } }
#else
	#define check(expr) { CA_ASSUME(expr); }
#endif


The reason for that is because Unreal4 uses several “#define check(expr)…” macros and sol2 uses check(expr) aswell, but in a different way, so check() needs to be undefined when including sol.hpp and then redefined when the include code returns to UE4.

There could also be compiler warnings like


warning C4628: digraphs not supported with -Ze. Character sequence '<:' not interpreted as alternate token for ''

But those can be ignored.
If you want to get rid of these warnings you can manually search for any occurence of “::std::” and “::sol::” in the sol.hpp and change it to “std::” and “sol::” (aka remove the “::” global scope prefixes so it only says “std::” and “sol::”), its only like 4 lines

So if anyone else needs a great and fast C++ Lua Wrapper for UE4, feel free to use Sol2 click
Happy scripting :slight_smile: