callExtension: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
mNo edit summary
(new interface)
(4 intermediate revisions by the same user not shown)
Line 13: Line 13:
Currently there is no limit how much data you can send to the extension. However there is a limit on how much data you can return from extension in one call. The limit is known to the extension and is passed in <tt> int outputSize</tt>. The limit may or may not change in the future and is currently 10240 bytes. It is up to extension designer to handle multipart results if returned data exceeds output limit.
Currently there is no limit how much data you can send to the extension. However there is a limit on how much data you can return from extension in one call. The limit is known to the extension and is passed in <tt> int outputSize</tt>. The limit may or may not change in the future and is currently 10240 bytes. It is up to extension designer to handle multipart results if returned data exceeds output limit.
<br><br>
<br><br>
Since Arma 3 v1.67 it is possible to pass array of arguments to extensions. The array of arguments could be anything and all elements will be converted to strings, however you might want to only send simple types like [[Boolean]]s, [[String]]s, [[Number]]s and [[Array]]s of all of the above. There is currently a limit on how many arguments can be send and is 1024. However an argument could be an [[Array]] itself, in this case extension maker will have to provide additional methods for parsing such arguments.
Since Arma 3 v1.67 it is possible to pass array of arguments to extensions. The array of arguments could be anything and all elements will be converted to strings, however you might want to only send simple types like [[Boolean]]s, [[String]]s, [[Number]]s and [[Array]]s of all of the above. There is currently a limit on how many arguments can be sent and it is 1024. However an argument could be an [[Array]] itself, in this case extension maker will have to provide additional methods for parsing such arguments.
<br><br>
<br><br>
Possible error codes:
Possible error codes:
Line 22: Line 22:
Each error will have entry in .rpt file with more details.
Each error will have entry in .rpt file with more details.
<br><br>
<br><br>
Since Arma 3 v1.69, <tt>RVExtensionVersion</tt> interface (see source code example below) has been added, which is called by the engine on extension load and expects extension version. This interface is designed to work with both, Linux and Windows. The max buffer size is 32 bytes. The version information will then appear in .[[rpt]] file like so:
<code>19:06:36 CallExtension loaded: test_extension (.\test_extension.dll) [1.0.0.1]</code>
<br>
For more information see [[Extensions]].
For more information see [[Extensions]].


Line 30: Line 33:


|p1= extension: [[String]] - extension name |= Parameter 1
|p1= extension: [[String]] - extension name |= Parameter 1
|p2= function: [[String]] - data send to the extension |= Parameter 2
|p2= function: [[String]] - data sent to the extension |= Parameter 2


| [[String]] - data sent back from extension |= Return value
| [[String]] - data sent back from extension |= Return value
Line 52: Line 55:
_result = "test_extension" [[callExtension]] ["fnc1", [[getUnitLoadout]] [[player]]];
_result = "test_extension" [[callExtension]] ["fnc1", [[getUnitLoadout]] [[player]]];
_result = "test_extension" [[callExtension]] ["fnc2", [[magazinesAmmoFull]] [[player]]];
_result = "test_extension" [[callExtension]] ["fnc2", [[magazinesAmmoFull]] [[player]]];
_result = "test_extension" [[callExtension]] ["fnc1", <nowiki>[</nowiki>[[weapons]] [[player]], [[magazines]] [[player]]]];</code>
_result = "test_extension" [[callExtension]] ["fnc1", <nowiki>[</nowiki>[[weapons]] [[player]], [[magazines]] [[player]]]];</code>|=
 
|x3= <code>_result = "test_extension" [[callExtension]] ["fnc1", [1,"two",[[true]],[4,"five",[[false]]]]];
[[parseSimpleArray]] (_result [[select]] 0) [[params]] ["_number","_string","_boolean","_array"];
[[systemChat]] [[str]] [_number,_string,_boolean,_array];</code>
<br>
<br>
<u>Source Code</u> ([http://data.bistudio.com/test_extension.zip Download .dll])<br><br>
<u>Source Code</u> ([http://data.bistudio.com/a3data/test_extension.zip Download .dll])<br><br>
This is an example of an extension compatible with both syntaxes. When using 1st syntax, the data is just copied from input to output. When using alt syntax, the arguments are parsed and then assembled back into string array in 2 ways: fnc1 and fnc2. fnc1 is a fraction faster.
This is an example of an extension compatible with both syntaxes. When using 1st syntax, the data is just copied from input to output. When using alt syntax, the arguments are parsed and then assembled back into string array in 2 ways: fnc1 and fnc2. fnc1 is a fraction faster.
<syntaxhighlight lang=cpp>
<syntaxhighlight lang=cpp>
Line 61: Line 68:
#include <iterator>
#include <iterator>
#include <sstream>
#include <sstream>
#define CURRENT_VERSION "1.0.0.1"


extern "C"
extern "C"
{
{
//--- Engine called on extension load
__declspec (dllexport) void __stdcall RVExtensionVersion(char *output, int outputSize);
//--- STRING callExtension STRING
//--- STRING callExtension STRING
__declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
__declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
//--- STRING callExtension ARRAY
//--- STRING callExtension ARRAY
__declspec (dllexport) int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argsCnt);
__declspec (dllexport) int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argsCnt);
}
//--- Extension version information shown in .rpt file
void __stdcall RVExtensionVersion(char *output, int outputSize)
{
//--- max outputSize is 32 bytes
strncpy_s(output, outputSize, CURRENT_VERSION, _TRUNCATE);
}
}



Revision as of 20:22, 28 April 2017

Hover & click on the images for description

Description

Description:
Calls custom .dll also known as Extension. The name of the extension is the name of the extension .dll without ".dll" part (or without "_x64.dll" part on 64-bit Arma). For example if the file is 'myExtension.dll' the name of the extension will be "myExtension". For 64-bit extensions, the name of the extension doesn't need to change and is still "myExtension". The game will automatically look for 'myExtension_x64.dll' when you use 64-bit Arma exe.

This command is blocking, meaning that the game will wait for the extension to return before continuing. This may cause FPS drop if extension is not optimised. If extension takes too long, consider making asynchronous extension, where the result of the work of the extension is collected in a separate call.

Currently there is no limit how much data you can send to the extension. However there is a limit on how much data you can return from extension in one call. The limit is known to the extension and is passed in int outputSize. The limit may or may not change in the future and is currently 10240 bytes. It is up to extension designer to handle multipart results if returned data exceeds output limit.

Since Arma 3 v1.67 it is possible to pass array of arguments to extensions. The array of arguments could be anything and all elements will be converted to strings, however you might want to only send simple types like Booleans, Strings, Numbers and Arrays of all of the above. There is currently a limit on how many arguments can be sent and it is 1024. However an argument could be an Array itself, in this case extension maker will have to provide additional methods for parsing such arguments.

Possible error codes:
  • 101: SYNTAX_ERROR_WRONG_PARAMS_SIZE
  • 102: SYNTAX_ERROR_WRONG_PARAMS_TYPE
  • 201: PARAMS_ERROR_TOO_MANY_ARGS
  • 301: EXECUTION_WARNING_TAKES_TOO_LONG
Each error will have entry in .rpt file with more details.

Since Arma 3 v1.69, RVExtensionVersion interface (see source code example below) has been added, which is called by the engine on extension load and expects extension version. This interface is designed to work with both, Linux and Windows. The max buffer size is 32 bytes. The version information will then appear in .rpt file like so: 19:06:36 CallExtension loaded: test_extension (.\test_extension.dll) [1.0.0.1]
For more information see Extensions.
Groups:
Uncategorised

Syntax

Syntax:
extension callExtension function
Parameters:
extension: String - extension name
function: String - data sent to the extension
Return Value:
String - data sent back from extension

Alternative Syntax

Syntax:
extension callExtension [function, arguments]         (Since Arma 3 v1.67)
Parameters:
extension: String - extension name
[function, arguments]: Array - callExtension params
function: String - extension function identifier
arguments: Array - function arguments. Could be array of Anything, each element will be converted to String automatically. Current allowed max length of this array is 1024
Return Value:
Array - in format [result, returnCode, errorCode], where:
  • result: String - data sent back from extension. It is up to extension maker what it is.
  • returnCode: Number - integer return from extension method. It is up to extension maker to define it.
  • errorCode: Number - error code in case of command error (see description). 0 means no errors.

Examples

Example 1:
_return = "myExtension" callExtension "stringToBeParsed";
Example 2:
_result = "test_extension" callExtension str weapons player; _result = "test_extension" callExtension ["fnc1", getUnitLoadout player]; _result = "test_extension" callExtension ["fnc2", magazinesAmmoFull player]; _result = "test_extension" callExtension ["fnc1", [weapons player, magazines player]];
Example 3:
_result = "test_extension" callExtension ["fnc1", [1,"two",true,[4,"five",false]]]; parseSimpleArray (_result select 0) params ["_number","_string","_boolean","_array"]; systemChat str [_number,_string,_boolean,_array];
Source Code (Download .dll)

This is an example of an extension compatible with both syntaxes. When using 1st syntax, the data is just copied from input to output. When using alt syntax, the arguments are parsed and then assembled back into string array in 2 ways: fnc1 and fnc2. fnc1 is a fraction faster.
#include <string>
#include <vector>
#include <iterator>
#include <sstream>

#define CURRENT_VERSION "1.0.0.1"

extern "C"
{
	//--- Engine called on extension load 
	__declspec (dllexport) void __stdcall RVExtensionVersion(char *output, int outputSize);
	//--- STRING callExtension STRING
	__declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
	//--- STRING callExtension ARRAY
	__declspec (dllexport) int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argsCnt);
}

//--- Extension version information shown in .rpt file
void __stdcall RVExtensionVersion(char *output, int outputSize)
{
	//--- max outputSize is 32 bytes
	strncpy_s(output, outputSize, CURRENT_VERSION, _TRUNCATE);
}

//--- name callExtension function
void __stdcall RVExtension(char *output, int outputSize, const char *function)
{
	std::string str = function;
	strncpy_s(output, outputSize, ("Input Was: " + str).c_str(), _TRUNCATE);
}

//--- name callExtension [function, args]
int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argsCnt)
{
	if (strcmp(function, "fnc1") == 0)
	{
		//--- Manually assemble output array
		int i = 0;
		std::string str = "[";

		//--- Each argument can be accessed via args[n]
		if (argsCnt > 0)
			str += args[i++];

		while (i < argsCnt)
		{
			str += ",";
			str += args[i++];
		}

		str += "]";

		//--- Extension result
		strncpy_s(output, outputSize, str.c_str(), _TRUNCATE);

		//--- Extension return code
		return 100;
	}

	else if (strcmp(function, "fnc2") == 0)
	{
		//--- Parse args into vector
		std::vector<std::string> vec(args, std::next(args, argsCnt));

		std::ostringstream oss;
		if (!vec.empty())
		{
			//--- Assemble output array
			std::copy(vec.begin(), vec.end() - 1, std::ostream_iterator<std::string>(oss, ","));
			oss << vec.back();
		}

		//--- Extension result
		strncpy_s(output, outputSize, ("[" + oss.str() + "]").c_str(), _TRUNCATE);

		//--- Extension return code
		return 200;
	}

	else
	{
		strncpy_s(output, outputSize, "Avaliable Functions: fnc1, fnc2", outputSize - 1);
		return -1;
	}
}

Additional Information

See also:
callcompileparseSimpleArrayExtensions

Notes

Report bugs on the Feedback Tracker and/or discuss them on the Arma Discord or on the Forums.
Only post proven facts here! Add Note

Notes

Bottom Section