Export Functions
Guide to export functions from your C++ plugin to be used by other language modules within Plugify.
In the Plugify ecosystem, C++ plugins can export functions to make them accessible to other plugins. This guide explains how to export functions in C++ and provides examples to help you integrate your plugins seamlessly.
Basic Type Mapping
The following table lists how types are exposed to the C++ API:
| C++ Type | Plugify Alias | Ref Support ? |
|---|---|---|
| void | void | ❌ |
| bool | bool | ✅ |
| char | char8 | ✅ |
| char16_t | char16 | ✅ |
| int8_t | int8 | ✅ |
| int16_t | int16 | ✅ |
| int32_t | int32 | ✅ |
| int64_t | int64 | ✅ |
| uint8_t | uint8 | ✅ |
| uint16_t | uint16 | ✅ |
| uint32_t | uint32 | ✅ |
| uint64_t | uint64 | ✅ |
| uintptr_t | ptr64 | ✅ |
| uintptr_t | ptr32 | ✅ |
| float | float | ✅ |
| double | double | ✅ |
| void* | function | ❌ |
| plg::string | string | ✅ |
| plg::any | any | ✅ |
| plg::vector<bool> | bool[] | ✅ |
| plg::vector<char> | char8[] | ✅ |
| plg::vector<char16_t> | char16[] | ✅ |
| plg::vector<int8_t> | int8[] | ✅ |
| plg::vector<int16_t> | int16[] | ✅ |
| plg::vector<int32_t> | int32[] | ✅ |
| plg::vector<int64_t> | int64[] | ✅ |
| plg::vector<uint8_t> | uint8[] | ✅ |
| plg::vector<uint16_t> | uint16[] | ✅ |
| plg::vector<uint32_t> | uint32[] | ✅ |
| plg::vector<uint64_t> | uint64[] | ✅ |
| plg::vector<uintptr_t> | ptr64[] | ✅ |
| plg::vector<uintptr_t> | ptr32[] | ✅ |
| plg::vector<float> | float[] | ✅ |
| plg::vector<double> | double[] | ✅ |
| plg::vector<plg::string> | string[] | ✅ |
| plg::vector<plg::any> | any[] | ✅ |
| plg::vector<plg::vec2> | vec2[] | ✅ |
| plg::vector<plg::vec3> | vec3[] | ✅ |
| plg::vector<plg::vec4> | vec4[] | ✅ |
| plg::vector<plg::mat4x4> | mat4x4[] | ✅ |
| plg::vec2 | vec2 | ✅ |
| plg::vec3 | vec3 | ✅ |
| plg::vec4 | vec4 | ✅ |
| plg::mat4x4 | mat4x4 | ✅ |
Exporting Functions in C++
To export a function in a C++ plugin, you need to ensure that the function is visible to other plugins. This is typically done by marking the function with the PLUGIN_API macro, which ensures the function is exported when the plugin is compiled as a dynamic link library (DLL).
Key Points
- Static Functions: Exported functions should generally be
staticto avoid requiring an object instance for invocation. - C Linkage: The
PLUGIN_APImacro does not automatically includeextern "C"to prevent name mangling. We need ensure the function can be found just by name by addingextern "C". - Parameter and Return Types: Use Plugify's native types (e.g.,
plg::string,plg::vector) for seamless integration.
Generating the PLUGIN_API Macro
The PLUGIN_API macro is generated using CMake. Here’s how you can set it up in your CMakeLists.txt file:
This generates a header file (module_export.h) that defines the PLUGIN_API macro. Include this header in your plugin source files to mark functions for export.
Basic Example
Here’s a simple example of exporting a function in a C++ plugin:
Function Definition
Exporting the Function
When the plugin is loaded, the function AddNumbers will be exported and can be called by other plugins.
Plugin Manifest Example
All exported functions must be described in the plugin's manifest file under the methods section. Here’s an example manifest for a plugin that exports the AddNumbers function:
Advanced Example: Exporting Complex Functions
Here’s an example of exporting a function with complex parameter and return types:
Function Definition
Plugin Manifest
Exporting Functions with References
C++ allows you to export functions that take parameters by reference, enabling the function to modify the caller's values.
Function Definition
Plugin Manifest
Note: In the manifest, set "ref": true for parameters that should be passed by reference. This tells Plugify to pass the parameter as a mutable reference.
Handling Callbacks
Plugify allows you to export functions that accept callbacks as parameters. Here’s an example:
Function Definition
Plugin Manifest
Automating Manifest Generation
New: You can now automate the generation of the methods section in your plugin manifest using clang-doc and a Python parser!
Instead of manually writing the manifest JSON for each exported function, you can use automated tools to extract function signatures, types, parameter descriptions, and even enum definitions directly from your C++ source code.
Benefits of Automated Generation
- No Manual JSON Writing: Function signatures are automatically extracted from your code
- Complete Type Information: Enum structures and function typedefs are included automatically
- Documentation Integration: Doxygen comments are parsed and included in the manifest
- Reduced Errors: Eliminates typos and type mismatches between code and manifest
- Easy Maintenance: Changes to function signatures are automatically reflected
Setup: Adding Documentation Generation to CMake
Add the following to your CMakeLists.txt to generate documentation and manifest JSON:
Using the Parser
Install the Parser
Download parser.py and place it in your project (e.g., in a tools/ directory).
Install dependencies:
Document Your Functions
Add Doxygen comments to your exported functions:
Document Enums and Typedefs
Document your enums and function typedefs:
Generate Documentation
Build the documentation target:
This generates docs/index.yaml with all your function information.
Parse to JSON
Run the parser to convert YAML to the manifest format:
Or with filtering:
Use in Your Manifest
Copy the generated methods array from exported_methods.json into your plugin manifest:
Advanced: Enum Structures
The parser automatically includes complete enum definitions when a parameter uses an enum type:
Generated Output:
Advanced: Function Typedefs
Function pointer typedefs are automatically parsed into complete prototypes:
Generated Output:
Note: Function typedef parameter names are auto-generated as param1, param2, etc. You may want to customize these in the manifest for better documentation.
Best Practices
- Use
PLUGIN_API: Always use thePLUGIN_APImacro to mark functions for export. - Follow Type Conventions: Adhere to Plugify's type conventions for parameters and return values.
- Document Your Functions: Use Doxygen-style comments (
@brief,@param,@return) to document exported functions. - Automate When Possible: Use the clang-doc parser to automate manifest generation and reduce manual errors.
- Document Enums and Typedefs: Include Doxygen comments on enums and typedefs for complete manifest generation.
- Test Thoroughly: Test your exported functions to ensure they work as expected when called by other plugins.
- Keep Manifests Updated: If using manual manifests, ensure they stay synchronized with your code. If using automation, regenerate after changes.
Conclusion
Exporting functions in C++ plugins is straightforward when you follow Plugify's conventions and best practices. By using the PLUGIN_API macro, adhering to type conventions, and optionally automating manifest generation with clang-doc and the Python parser, you can create robust and interoperable plugins with minimal manual effort. For more advanced use cases, such as handling callbacks or working with enums, the automated parser provides complete type information including enum structures and function prototypes.