Develop WasmEdge Plug-in in C API
Prerequisites
For developing the WasmEdge plug-in in C API, please install WasmEdge first.
Example
Assume that the plug-in example is in the file testplugin.c
.
Host Functions
The goal of the plug-in is to provide the host functions which can be imported when instantiating WASM. Therefore, developers can implement their plug-in host functions first, as the same as the host functions in WasmEdge C API.
For the more details about the external data and calling frame context, please refer to the host function guide.
#include <wasmedge/wasmedge.h>
/* The host function definitions. */
/* The host function to add 2 int32_t numbers. */
WasmEdge_Result HostFuncAdd(void *Data,
const WasmEdge_CallingFrameContext *CallFrameCxt,
const WasmEdge_Value *In, WasmEdge_Value *Out) {
int32_t Val1 = WasmEdge_ValueGetI32(In[0]);
int32_t Val2 = WasmEdge_ValueGetI32(In[1]);
Out[0] = WasmEdge_ValueGenI32(Val1 + Val2);
return WasmEdge_Result_Success;
}
/* The host function to sub 2 int32_t numbers. */
WasmEdge_Result HostFuncSub(void *Data,
const WasmEdge_CallingFrameContext *CallFrameCxt,
const WasmEdge_Value *In, WasmEdge_Value *Out) {
int32_t Val1 = WasmEdge_ValueGetI32(In[0]);
int32_t Val2 = WasmEdge_ValueGetI32(In[1]);
Out[0] = WasmEdge_ValueGenI32(Val1 - Val2);
return WasmEdge_Result_Success;
}
Host Modules
Then developers should implement the module creation functions.
Noticed that there can be several module instances in a plug-in shared library.
Here take a module named as wasmedge_plugintest_c_module
for the example.
/* The creation function of creating the module instance. */
WasmEdge_ModuleInstanceContext *
CreateTestModule(const struct WasmEdge_ModuleDescriptor *Desc) {
/*
* The `Desc` is the const pointer to the module descriptor struct:
*
* typedef struct WasmEdge_ModuleDescriptor {
* const char *Name;
* const char *Description;
* WasmEdge_ModuleInstanceContext *(*Create)(
* const struct WasmEdge_ModuleDescriptor *);
* } WasmEdge_ModuleDescriptor;
*
* Developers can get the name and the description from this descriptor.
*/
/* Exported module name of this module instance. */
WasmEdge_String ModuleName =
WasmEdge_StringCreateByCString("wasmedge_plugintest_c_module");
WasmEdge_ModuleInstanceContext *Mod =
WasmEdge_ModuleInstanceCreate(ModuleName);
WasmEdge_StringDelete(ModuleName);
WasmEdge_String FuncName;
WasmEdge_FunctionTypeContext *FType;
WasmEdge_FunctionInstanceContext *FuncCxt;
enum WasmEdge_ValType ParamTypes[2], ReturnTypes[1];
ParamTypes[0] = WasmEdge_ValType_I32;
ParamTypes[1] = WasmEdge_ValType_I32;
ReturnTypes[0] = WasmEdge_ValType_I32;
/* Create and add the host function instances into the module instance. */
FType = WasmEdge_FunctionTypeCreate(ParamTypes, 2, ReturnTypes, 1);
FuncName = WasmEdge_StringCreateByCString("add");
FuncCxt = WasmEdge_FunctionInstanceCreate(FType, HostFuncAdd, NULL, 0);
WasmEdge_ModuleInstanceAddFunction(Mod, FuncName, FuncCxt);
WasmEdge_StringDelete(FuncName);
FuncName = WasmEdge_StringCreateByCString("sub");
FuncCxt = WasmEdge_FunctionInstanceCreate(FType, HostFuncSub, NULL, 0);
WasmEdge_ModuleInstanceAddFunction(Mod, FuncName, FuncCxt);
WasmEdge_StringDelete(FuncName);
WasmEdge_FunctionTypeDelete(FType);
return Mod;
}
Plug-in Descriptions
For constructing the plug-in, developers should supply the descriptions of this plug-in and the modules.
/* The module descriptor array. There can be multiple modules in a plug-in. */
static WasmEdge_ModuleDescriptor ModuleDesc[] = {{
/*
* Module name. This is the name for searching and creating the module
* instance context by the `WasmEdge_PluginCreateModule()` API.
*/
.Name = "wasmedge_plugintest_c_module",
/* Module description. */
.Description = "This is for the plugin tests in WasmEdge C API.",
/* Creation function pointer. */
.Create = CreateTestModule,
}};
/* The plug-in descriptor */
static WasmEdge_PluginDescriptor Desc[] = {{
/*
* Plug-in name. This is the name for searching the plug-in context by the
* `WasmEdge_PluginFind()` API.
*/
.Name = "wasmedge_plugintest_c",
/* Plug-in description. */
.Description = "",
/* Plug-in API version. */
.APIVersion = WasmEdge_Plugin_CurrentAPIVersion,
/* Plug-in version. Developers can define the version of this plug-in. */
.Version =
{
.Major = 0,
.Minor = 1,
.Patch = 0,
.Build = 0,
},
/* Module count in this plug-in. */
.ModuleCount = 1,
/* Plug-in option description count in this plug-in (Work in progress). */
.ProgramOptionCount = 0,
/* Pointer to the module description array. */
.ModuleDescriptions = ModuleDesc,
/* Pointer to the plug-in option description array (Work in progress). */
.ProgramOptions = NULL,
}};
Plug-in Options
WORK IN PROGRESS. This section is reserved for the feature in the future.
Implement the Get Descriptor API
The final step is to implement the WasmEdge_Plugin_GetDescriptor()
API to return the plug-in descriptor.
WASMEDGE_CAPI_PLUGIN_EXPORT const WasmEdge_PluginDescriptor *
WasmEdge_Plugin_GetDescriptor(void) {
return &Desc;
}
Build
To build the plug-in shared library, developers can choose to build stand-alone by the compiler or use cmake.
Build with Command
clang -shared -std=c11 -DWASMEDGE_PLUGIN testplugin.c -lwasmedge -o libwasmedgePluginTest.so
Build in CMake
add_library(wasmedgePluginTest
SHARED
testplugin.c
)
set_target_properties(wasmedgePluginTest PROPERTIES
C_STANDARD 11
)
target_compile_options(wasmedgePluginTest
PUBLIC
-DWASMEDGE_PLUGIN
)
target_link_libraries(wasmedgePluginTest
PRIVATE
wasmedge
)