Plugins allow you to extend the functionality of Solar2D. This guide outlines the fundamental details.
Solar2D runs Solar2D Free Plugin directory at plugins.solar2d.com. If you created a plugin please submit it to the Solar2D Free Plugin Directory. You can either submit link where one can get your plugin, or distribute it for free. Alternatively, you may submit it to the Solar2D Plugins Marketplace, please see the Asset Packaging Guidelines.
Solar2D plugins leverage Lua's module system in which plugins are lazily loaded by a corresponding call to the Lua require() function.
Typically, these plugins are just shared native libraries which are supported on platforms like .dylib
).dll
).so
)
.a
)..jar
).In these two cases, Solar2D adds special loaders which ensure that these plugins can be easily loaded, assuming certain conventions are followed.
Plugins for Solar2D are hosted in a number of places. Many are available at Free Plugins Directory, Solar2D Marketplace, and Solar2D Plugins Marketplace. You can incorporate a plugin by adding an entry to the plugins
table of build.settings
, for example:
settings = { plugins = { ["plugin.myPlugin"] = { publisherId = "com.domainname" }, }, }
Each plugin host will provide specific build.settings for the individual plugin.
When added in this manner, Solar2D will integrate the plugin during the build phase.
From there, the plugin can be loaded using the standard Lua require() function, for instance:
local myPlugin = require( "plugin.myPlugin" )
Native plugins can easily be added to your iOS or Android project.
On iOS, plugins will be in the form of static library (.a
) files that need to be linked into your app executable.
On Android, plugins can come in the form of .so
(shared library), .jar
or .aar
files.
When you add a plugin via Solar2D Native, be aware of the following:
If you want to create/submit a plugin for availability in the Solar2D Plugins Marketplace, you can use our App
project templates to simplify development of your plugin, as well as test it. After all, a plugin itself is not an executable and it must be run inside an actual application. The project templates can be located within the Solar2D Native folder:
/Applications/Corona/Native/Project Template/App/
This folder has separate
ios
android
There's also a Corona
folder that sits alongside these folders which contains a classic Corona project (main.lua
). You can modify these files to test the Lua APIs that are offered by your plugin.
In the ios
folder, there are two Xcode projects:
App.xcodeproj
— This is the project that builds the .app
executable which runs on the device. It automatically builds the plugin as an implicit dependency.
Plugin.xcodeproj
— For plugin development, you should modify this project. It builds the plugin as a static library (.a
) and you can use this project directly if you want to share your plugin outside of the App
project.
Most often, you will want to create a universal binary for your plugin. In other words, you'd like to ship one static library that supports both the device and the
You can accomplish this via the lipo
tool. In the following example, we are creating a universal library for staticlibrary.a
:
lipo -create "/path/to/iphoneos/staticlibrary.a" "/path/to/iphoneos-simulator/staticlibrary.a" -output "/path/to/dst/staticlibrary.a"
In the android
folder, the contents include:
app
— This module builds the .apk
that installs on the device. The app
module automatically builds the plugin as an explicit dependency per this entry in the dependencies
block of the build.gradle
script for the app
module (compile project(':plugin')
).
plugin
— This module builds the plugin as a .jar
file, only including the Java files under plugin/src/main/java
in your project. You can use this project directly if you want to share your plugin outside of the App
project.
Plugins build upon Lua's module system, so they can come in three different flavors:
A Lua library plugin can be created using the CoronaLibrary class. Please see the Creating Lua Plugins guide for details on how to create, package, and submit a Lua plugin to the available marketplaces.
In addition to the plugin naming conventions discussed above, Solar2D expects plugins to follow some additional conventions that ensure Lua can locate these modules. In C, these conventions are just the standard Lua naming conventions for modules:
luaopen_
..
), it is replaced by an underscore (_
) in the name of the function, since C does not allow dots in symbol names.For example, the Lua library plugin.myLibrary
would have a Lua function called luaopen_plugin_myLibrary
:
static int doSomething( lua_State *L ) { lua_getglobal( L, "print" ); lua_pushstring( "I did something!" ); CoronaLuaDoCall( L, 1, 0 ); return 0; } // Export so it's visible to "require()" CORONA_EXPORT int luaopen_plugin_myLibrary( lua_State *L ) { static const luaL_Reg kFunctions[] = { { "doSomething", doSomething }, { NULL, NULL } }; // Create "myLibrary" // Lua version assumes version and revision default to 1 int result = CoronaLibraryNew( L, "myLibrary", "com.mycompany", 1, 1, kFunctions, NULL ); return result; }
If you write the module in Java, Corona has set up Lua to load Java code and to let that Java code define the Lua library via JNLua. Here, Lua looks for the Java class LuaLoader
and instantiates it.
Solar2D assumes the following conventions:
LuaLoader
class has a default (empty) constructor.LuaLoader
class must implement the JNLua interface com.naef.jnlua.JavaFunction
.LuaLoader
should be the same as the name passed to require()
.For example, the Lua library plugin.myLibrary
would be implemented by the plugin.myLibrary.LuaLoader
and that class would implement the invoke()
method of the com.naef.jnlua.JavaFunction
interface.
You can also create plugins in a hybrid fashion. For example, you can create the library via Lua code and then do further initialization in C.
Below is an example for creating the myLibrary
library from Lua and then adding additional functions on the native C side. Here, we assume kBuffer
stores the Lua bytecodes corresponding to myLibrary.lua
.
// The bytecodes for "myLibrary.lua" are contained in kBuffer static const unsigned char kBuffer[] = { ... } static int bufferLoader( lua_State *L ) { return luaL_loadbuffer( L, (const char*)kBuffer, sizeof( kBuffer ), "myLibrary" ); } static int somethingElse( lua_State *L ) { printf( "I'm doing something else!" ); return 0; } CORONA_EXPORT int luaopen_myLibrary( lua_State *L ) { lua_CFunction factory = Corona::Lua::Open< bufferLoader >; int result = CoronaLibraryNewWithFactory( L, factory, NULL, NULL ); if ( result ) { const luaL_Reg kFunctions[] = { { "somethingElse", somethingElse }, { NULL, NULL } }; luaL_register( L, NULL, kFunctions ); } return result; }