Native Extensions

We have been hard at work with a feature dubbed NativeExtensions. You might have seen some snippets and teasers of this elsewhere on the forums, but we wanted to give everyone a short overview of the current state and where we are headed.

Background

Since we launched Defold we have received requests from external users (and internal) to be able to extend the engine using C/C++/ObjC/Java code. This would enable users to access and expose native functionality that Defold does not currently expose or have; examples range from adding third party ad libraries, SteamWorks SDK or platform specific features such as Apple Game Center.

Thankfully the engine is already built with this extendability in mind, our Facebook module is a good example of this which is one of many features built as an extension internally.

But just as any other feature in the Defold services, we want to expose such functionality to our users in a stable and easy-to-use way as possible.

What is an extension?

We want to keep the ease of having everything related to a game project inside the editor, or more specifically, keep everything in the game project. In its current form an extension is defined as a separate folder in your project with an accompanied manifest file describing any special compiler flags or libraries needed to build. This means that extensions can be part of your game project, just as any other resource you currently have, but also be included as Defold libraries.

On a technical level an extension will implement a few specific functions that the engine will call at different times, such as; app initialization/finalization, script initialization/finalization and frame update.

A bare minimum C++ code example;

#include <dmSDK/dmSDK.h>

static dmExtension::Result AppInitializeExtension(dmExtension::AppParams* params)
{
    return dmExtension::RESULT_OK;
}

static dmExtension::Result AppFinalizeExtension(dmExtension::AppParams* params)
{
    return dmExtension::RESULT_OK;
}

static dmExtension::Result UpdateExtension(dmExtension::Params* params)
{
    return dmExtension::RESULT_OK;
}

static dmExtension::Result InitializeExtension(dmExtension::Params* params)
{
    return dmExtension::RESULT_OK;
}

static dmExtension::Result FinalizeExtension(dmExtension::Params* params)
{
    return dmExtension::RESULT_OK;
}

DM_DECLARE_EXTENSION(MyCoolExtension, "my_cool_extension", AppInitializeExtension, AppFinalizeExtension, InitializeExtension, UpdateExtension, 0, FinalizeExtension)

Defold SDK

For users to build upon Defold in a meaningful way we are going to supply a new artifact with each release that includes headers and libraries to build and interact with the engine.

Extender Server and Service

Not everyone is a coder, so to be able to build the engine without having to setup a complex dev environment we are going to supply a free cloud service that can build engine binaries for all our supported platforms. This service is something the editor (Editor v1, v2 and Bob) will communicate with and trigger build commands behind the scenes. So everyone on your team just need to open the project and press Build and Launch and let the editor work its magic. :slight_smile:

A discussion board post is maybe not the best forum (he he) to go into more details, particularly since we are in the middle of hammering out everything. But to peek your interest, here is a super simple extension example running AdMob on an iOS device:

18 Likes

@jakob.pogulis @sven I have no words, just emotions. :grinning::joy:

Does this mean that you disassemble the engine into modules ?
as I told in

2 Likes

In short, yes.
The SDK will contain the libraries, and later on we will be able to exclude unused libraries from the build, thus minimizing the build size.

5 Likes

@sven What’s the ETA on this? I want it bad :grin: Game Center and my preferred ad networks are the main things I need before we can consider going Defold 100%. Are you planning to bundle any extensions other than Facebook? I’d like to see Game Center in particular.

4 Likes

Who said you have to hate Mondays???

Great job guys!!! Seems both these features are really well thought.

4 Likes

The point of creating a public Native Extension system is that the community can create and share useful extensions so that not all the work has to be done by the engine team (although I’m guessing some of us will create extensions as well). The extensions will be just like any other Defold library project and can thus be shared just as easily.

10 Likes

You guys are awesome!
Congrats after all that hard work I know you have put into it

6 Likes

That’s awesome! Will this support integration with the renderer? I saw you posted a demo a while back playing a video inside a texture. To what extent do we have control over textures / meshes / drawing code / the GLES state?

3 Likes

If all goes as planned, we want to have an initial beta of sorts available around GDC. What platforms or to what extent this beta means I’m not 100% sure at the moment, but will keep you guys updated.

At launch we will not supply any extensions ourselves, but instead some examples and getting started manuals/tutorials so the community can start creating/experimenting. But in the long run we want to “break out” some of our internal “extensions” (as you mentioned for example Facebook) to be real extensions. This means somewhere down the line you will be able to just depend on the official Facebook extension as a library, or a third party one, and not be forced to have it in the binary as you currently are. :thumbsup:

There will be a couple of new scripting modules with the extensions system, one example is the resource.* which can be used to update resources at runtime. Currently we are experimenting with texture resources, which our video player extension uses to update a texture with the video output in runtime.

We want to add more resources that can be changed at runtime than just textures, like meshes and sound, but I’m not sure how many will be available in the first release. (Not sure about drawing/rendering and GLES state stuff.)

6 Likes

Script files will probably have to be forced to always be white listed for initial bundling. They are usually the small parts anyway.

Thanks so much guys for all the hard work… Defold is King :slight_smile:

5 Likes

I got the example extension working :+1: Is it possible to include libs distributed as Apple frameworks yet? I can’t figure it out.

3 Likes

We will share more official examples soon, but what do you need specifically?

I’ve played around with a couple of different things and have some very unofficial samples in varying states of usefulness :slight_smile:

iOS Gyro using CoreMotion: https://github.com/britzl/gyrobomber/tree/master/gyro
Steamworks: https://github.com/britzl/steamworks-defold/tree/master/steamworks

There’s more if you look around, like a camera and videoplayer thing by Mathias and Sven, but they will be packaged into proper examples very soon I believe.

7 Likes

Thanks for the examples, I see some undocumented goodies there :grin: I want to make an AdMob extension, and I was going to do that via Firebase as that’s the preferred method, but Firebase libs for iOS are provided as .frameworks and CocoaPods. I can get around the CocoaPods, but I’m still left w/ 3rd party frameworks, and putting them directly in the extension’s /lib or /include didn’t seem to work. I suspect that I could pull the stuff out of the frameworks and include it directly in lib and include, but that’s not ideal, and with the builds being as opaque as they are right now, I don’t want to just keep trying stuff without knowing if I’m making progress.

I see that @sven actually has an AdMob extension in the first screenshot in this thread, but the folders aren’t expanded so I can’t see what’s in there :smiling_imp:

2 Likes

If I remember correctly, you should be able to put the .framework folders inside your lib/ios/ folder. :slight_smile:

4 Likes

FYI, @Andreas_Tadic and @sicher have now added the SDK documentation to the documentation page under the category Defold SDK

7 Likes

Yay, been needing this. :smiley: What happened to dmScript::Get/SetInstance? I’ve written an AdMob extension, and it almost works (I can show interstitials,) but any time I call a Defold fun from within a Lua callback (called from native extension code,) I get a crash. So, looking at @britzl’s Gyrobomber example made me think that the secret sauce I was missing was Get/SetInstance. Should I be able to call Defold funs from a Lua callback (via lua_call) without any special setting up of the context? The callback itself is actually called and I can do other things in it, I only crash when I call Defold funs from it.

6 Likes

Hi @nox!

Happy to see you’ve made such progress!
Yes, as you could tell, we hadn’t include some functions in the sdk yet, we’ll be sure to add them in the next release.
In the mean time, you should be able to forward declare the missing functions at the top of your .cpp-file, and you should be good to go. Let me know how it goes!

NOTE Beware that this code is subject to change until it’s released in the stable release :slight_smile:

namespace dmScript
{
    /**
     * Retrieve current instance from the global table and place it on the top of the stack, only valid when set.
     * @param lua state
     */
    void GetInstance(lua_State* L);
    /**
     * Set the value on the top of the stack as the instance into the global table and pops it from the stack.
     * @param lua state
     */
    void SetInstance(lua_State* L);
    /**
     * Check if the instance in the lua state is valid. The instance is assumed to have been previously set by SetInstance.
     * @param lua state
     * @return whether the instance is valid
     */
    bool IsInstanceValid(lua_State* L);
 
    /**
     * Retrieve the main thread lua state from any lua state (main thread or coroutine).
     * @param lua state
     * @return the main thread lua state
     */
    lua_State* GetMainThread(lua_State* L);
}
6 Likes

Hi everyone!

As promised, we’ve cleaned up and shared two native extension examples on github.
You can find them here:
Camera
Video Player

Hopefully, we can share more examples soon.

NOTE:
As mentioned in their readme’s, you should view these as (working) examples. Although we aim to keep them working and show some good practices on how to do things with Lua + extensions, at this point we will maintain them as just that, examples.

9 Likes

HI there!

Heres another small update:
We are continuing our work on the Android support, which is well underway, but still have some way to go before it’s considered fully working.

Also, we are working on a Lua api for our new “buffers”. The native extensions communicate with the engine via Lua, and with the help of our new buffers, they can pass large memory chunks between each other without doing memory duplication. With this Lua api, it will be possible to create such buffers directly from Lua, without the need of creating a native extension. Here is an example, we create a buffer, render a bunch of particles (simple plots) to that buffer, and set the texture on a sprite:

8 Likes