Revision Difference
Creating_Binary_Modules#544770
<cat>Dev</cat>
Binary modules allow you to extend Lua's functionality using C++.
# Headers⤶
⤶
The headers you need and an example are [available here](https://github.com/Facepunch/gmod-module-base/tree/development).
⤶
# Building⤶
⤶
To turn the example into a visual studio project you should download [premake4](https://github.com/premake/premake-core), place the premake5.exe file in the same directory as BuildProjects.bat (or ideally in your main windows folder), and then run BuildProjects.bat.
⤶
This will then create a folder called "windows-vs2010", which contains the Visual Studio project file.
⤶
Read up on how to use [Premake](https://github.com/premake/premake-core/wiki) to compile your modules for osx/linux.
# Dependencies⤶
⤶
Binary Modules only need CMake and a C++ compiler for building.
⤶
You can install both through either the Visual Studio Installer ("Desktop development with C++" in Visual Studio 2019) on Windows, Xcode/homebrew on macOS, or by using your favorite package manager on Linux.⤶
For CMake, downloads are also available on the [CMake website](https://cmake.org/download/).
⤶
If you want to use an IDE, you should be able to choose any as long as it has support for CMake projects (Visual Studio, CLion, etc.).
⤶
If you don't want to use an IDE you can also build the module manually, but that approach will not be detailed in this guide.
⤶
# Project setup⤶
⤶
The headers you need are [available here](https://github.com/Facepunch/gmod-module-base/tree/development).⤶
They will provide your project with information about how to interface with the game and set a few common settings for compiling the module.⤶
⤶
First, create an empty folder. This will contain all the files related to your module and will be referred to as "main folder" from now on.⤶
⤶
Now, download a copy of the headers into a subfolder of the main folder.⤶
While you can name it freely, for this guide I will use `gmod-headers` as the name of the subfolder.⤶
You will have to replace that name accordingly if you chose something different.⤶
To check whether you extracted the files in the correct location, make sure that the paths `gmod-headers/include` and `gmod-headers/examples` are present in the main folder.⤶
⤶
Next, we will set up a CMake project definition.⤶
To do that, create a file called `CMakeLists.txt` in the main folder and paste the following content in there:⤶
⤶
```⤶
cmake_minimum_required(VERSION 3.10)⤶
⤶
# The project name is rather unimportant and you can name it anything you want.⤶
# It just mustn't conflict with the module name that is defined further below.⤶
project(gmod-module-guide LANGUAGES CXX)⤶
⤶
set(CMAKE_CONFIGURATION_TYPES Release Debug)⤶
set(CMAKE_CXX_STANDARD 11)⤶
set(CMAKE_CXX_STANDARD_REQUIRED ON)⤶
⤶
# Load the gmod-module-base project that sets up headers and settings.⤶
add_subdirectory(gmod-headers/include)⤶
⤶
# The library name defined here (in this case, "testmodule") will be the name of the module.⤶
add_library(testmodule SHARED)⤶
⤶
# Add the source files required for the module.⤶
# Again, the file names don't matter and you can even add multiple files by adding more space-delimited filenames after "module.cpp".⤶
target_sources(testmodule PRIVATE module.cpp)⤶
⤶
# Actually apply the headers and settings to our module.⤶
target_link_libraries(testmodule gmod-module-base)⤶
⤶
set_gmod_suffix_prefix(testmodule)⤶
```⤶
⤶
Now that we have our project defined, we just need something that we can compile into a module.⤶
⤶
For demonstration purposes the "Hello World" example works just fine, so copy `gmod-headers/examples/HelloWorld/HelloWorld.cpp` and paste it into the main folder as `module.cpp`.⤶
This file you can now change and experiment with.⤶
⤶
For building, simply open the main folder in your chosen IDE (any half-decent one should detect the `CMakeLists.txt` file and set up a CMake project) and press "Build" in there.⤶
Developers without IDE can now follow any existing "how to build a CMake project" guide.⤶
The binary module will end up whereever the CMake output was placed, with the correct name already applied.⤶
# A note on userdata & metatables
Userdata and metatables are handled differently in Garry's Mod. This helps the engine determine userdata type much faster.
First create your metatable (ideally in GMOD_MODULE_OPEN), then create a reference to it and store it globally in a variable.
```
LUA->CreateTable();
LUA->PushCFunction(gcDeleteWrapper);
LUA->SetField(-2, "__gc");
LUA->PushCFunction(toStringWrapper);
LUA->SetField(-2, "__tostring");
LUA->PushCFunction(indexWrapper);
LUA->SetField(-2, "__index");
LUA->PushCFunction(newIndexWrapper);
LUA->SetField(-2, "__newindex");
metatable = LUA->ReferenceCreate();
```
To push your userdata to the stack:
```
GarrysMod::Lua::UserData* ud = ( GarrysMod::Lua::UserData* )LUA->NewUserdata( sizeof( GarrysMod::Lua::UserData ) );
ud->data = pointer_to_your_c_class;
ud->type = your_type_id;
LUA->ReferencePush( metatable );
LUA->SetMetaTable(-2);
```
To get your userdata from the stack:
```
GarrysMod::Lua::UserData* obj = (GarrysMod::Lua::UserData* )LUA->GetUserdata(position);
your_c_class* var = (your_c_class*)(obj->data);
```
# Naming & Location
The module files should be placed in the garrysmod/lua/bin/ folder.
The names differ between platform and Lua realm.
|File name|Side| require(name) | Platform |
|---|---|---|---|
| `gmsv_example_win32.dll` | Server | example | Windows x32 |
| `gmcl_example_win32.dll` | Client | example | Windows x32 |
| `gmsv_example_win64.dll` | Server | example | Windows x64 (`x86-64` branch is required) |
| `gmcl_example_win64.dll` | Client | example | Windows x64 (`x86-64` branch is required) |
| `gmsv_example_osx.dll` | Server | example | OSX (actually a `.so` file, just renamed) |
| `gmcl_example_osx.dll` | Client | example | OSX (actually a `.so` file, just renamed) |
| `gmsv_example_linux.dll` | Server | example | Linux (actually a `.so` file, just renamed) |
| `gmcl_example_linux.dll` | Client | example | Linux (actually a `.so` file, just renamed) |
# Converting From GMod 12
The interface in GMod 13 is very different to that of GMod 12 - the handy object wrappers are gone and the interface is very very similar to the standard Lua C API. Infact, nearly all of the functions in the interface work exactly the same way as their equivalents in the Lua C API, they're just named slightly differently.
You should be able to work out what most of the functions do from the example and the [Lua C API Documentation](http://www.lua.org/manual/5.2/manual.html#4.8).
If you find this kind of stack-level programming too hard, BlackAwps has created some "backwards headers", which should work exactly how the GMod 12 interface worked, you can find them [here](https://bitbucket.org/breakpointservers/bkacjios-glua-modules/src).⤶
⤶
If you find this kind of stack-level programming too hard, BlackAwps has created some "backwards headers", which should work exactly how the GMod 12 interface worked, you can find them [here](https://bitbucket.org/breakpointservers/bkacjios-glua-modules/src).