Feature #25915

Official support for 3rd party plugins (dll's)

Added by Sickboy almost 4 years ago. Updated over 1 year ago.

Status:In progress Start date:10/27/2011
Priority:Normal Due date:
Assignee:Dwarden % Done:

0%

Category:API
Target version:1.63 BETA
Affected ArmA II version:Please select... First affected ArmA II version:Please select...
Reproduced by another DH user:No Single / Multi Player?:
I am using some Mods:No BIForumURL:
I am using: NGUrl:
Reproducible for you:No WIKIurl:
Related to content of DLC:

Description

Instead of injection techniques, riding dsound.dll, and hijacking ingame functionality, more official support for 3rd party plugin (dll's).
Somewhat related: http://community.bistudio.com/wiki/ArmA_2:_Custom_Memory_Allocator
:)

Idea is if officially implemented API - the other holes could perhaps be closed, and security level raised, and BattlEye primed to detect and alert.

Also would be great to be able to specify which Signature and/or MD5Sum of plugin is allowed on clients (so Dedicated Server Setting)

Use cases:
  • ACRE (Advanced Radio Combat Environment) - TeamSpeak3
  • Access to SQL-like database for advanced mission / persistence purposes
  • WorldEditors like 3DE

Related issues

related to ARMA2 Community Issue Tracker - Bug #11701: sendUDPMessage function doesn't work Assigned 07/05/2010 12/01/2010
related to ARMA2 Community Issue Tracker - Feature #11743: Simple UDP Communication - sendUDPMessage Assigned 07/07/2010
related to ARMA2 Community Issue Tracker - Feature #9436: Implement Basic I/O so ArmA can talk to other applications Duplicate 03/05/2010
related to ARMA2 Community Issue Tracker - Feature #28539: Official support for Mumble's LINK - open plugin interfac... Assigned 02/09/2012
related to ARMA2 Community Issue Tracker - Feature #25606: Public availabile developer/debug version Assigned 10/18/2011
related to ARMA2 Community Issue Tracker - Feature #5892: Implement faceAPI Assigned 11/16/2009

History

Updated by Sickboy almost 4 years ago

  • Description updated (diff)

Updated by Sickboy almost 4 years ago

  • Description updated (diff)

Updated by Suma almost 4 years ago

  • Status changed from Assigned to In progress

You may be pleased to learn a planning on this has starting about 15 minutes ago. :)

Updated by Sickboy almost 4 years ago

  • Description updated (diff)

Updated by Sickboy almost 4 years ago

Suma wrote:

You may be pleased to learn a planning on this has starting about 15 minutes ago. :)

Pleased doesn't quite cut it Suma - I will respond back when I figured out what word(s) cut it!!! :D

Updated by Suma over 3 years ago

A first attempt, very modest and conservative, is present in 87640. The purpose of this step is to provide a clean method of the binding for JayArma2Lib instead of current kbAddString / dsound.dll hijacking.

A script can call a dll function using a new callExtension scripting funcion:

 ret = <extension name> callExtension <function name and arguments>

All values involved are string only, name of the extension is used to construct a dll name (.dll is added automatically), and the dll is searched in mod folders only, dll is loaded on a first call of call_extension with given extension name. Assuming the dll is called RVExtSample.dll, the call looks like:

output = "RVExtSample" callExtension "input"

The dll is expected to contain an entry point of a form _RVExtension@12, with a following C signature:

void __stdcall RVExtension(char *output, int outputSize, const char *function);

The game currently calls the RVExtension function with outputSize of 4096 (can be increased in future versions if needed, but I would like to avoid dynamically sized strings or any dynamically allocated memory if possible to keep the interface simple). If the function is to receive arguments, they can be concatenated to the function name and the dll is responsible to perform any spliting / parsing / decoding as needed.

The example dll source example follows. In this example the dll simply copies the input to the output:

// dllmain.cpp : Defines the entry point for the DLL application.
#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" 
{
  __declspec(dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); 
};

void __stdcall RVExtension(char *output, int outputSize, const char *function)
{
  strncpy(output,function,outputSize);
}

Updated by Sickboy over 3 years ago

I've got the following feedback from Nou:

[7:54:21] CD (Nou): the only thing i think would be a little bit nicer and provide some more ease of use for people is providing multiple arguments to it, because thats the only advantage the patched kbAddTopic has, it can take 4 args
[7:54:33] CD (Nou): and we dont have to parse them out in plugin
[7:54:36] CD (Nou): its not a HUGE deal
[7:54:40] CD (Nou): but it is more overhead
[7:54:48] CD (Nou): cause we have to build arg strings now

Updated by Suma over 3 years ago

right now its CTDs if it cant find it

Fixed in 87661. When not found, the return is empty string now. If you want to be able to check for an extension existence, be sure to provide some means in the extension, e.g. provide a "version" function, or some other function always returning a non-empty value.

Updated by Sickboy over 3 years ago

Thanks!

Another suggestion from Nou:

[18:12:16] CD (Nou): oh another feature that would be nice is if on game load and unload the dlls ran their normal entry and exit functionality

However I suppose that isn't feasable due to security concerns, now the addon/mission must call out to the extension, not the extension automatically performing actions.

However signature verification for the extensions could probably take care of that, at least partially.

Updated by Suma over 3 years ago

At this point I would most of all like to get following feedback:
- can this be used to replace dsound / kbAddTopic injection?
- are there any security or other serious issues which make this unsuitable for a stable release?

Updated by Suma over 3 years ago

It seems the JayArmA2Lib is already using this meanwhile: http://forums.bistudio.com/showpost.php?p=2083748&postcount=537

If there will be no more feedback here within a few days, I guess we will open this to public.

Updated by kju over 3 years ago

Right. So it seems to work well. Good job!

However this does not answer your two questions, does it?
The Arma2MySQL project might be another good candidate for quick adoption.

Jaynus should have the expertise to comment the security part;
so might some other community members once the API becomes known.

Updated by Sickboy over 3 years ago

Yes apparently the current implementation allowed Jay and Nou to successfully replace the dsound.dll hooks with the new callExtension: http://forums.bistudio.com/showthread.php?p=2083748#post2083748

Nothing on security concerns yet.
Though i'd say some means to verify dll authenticity locally but also remotely through signatures or similar would be needed,
so server admins can control what extensions may be loaded when connecting to a server.

Arma2MySQL uses JayArma2lib btw, but it is not yet known if it works with the new implementation afaik.

Updated by Dwarden over 3 years ago

why not use v2 signature system to create bisign file for the .dll

that way it can be easily controlled by allowed .bikey on server
as DLL can be signed by author easily same as PBO

note: this just hit me, DLLs inside \dll\ aren't signed either !

Updated by kju over 3 years ago

Ref Arma2MySQL

It's implemented in the latest jay2lib and working with our project just fine

Updated by kju over 3 years ago

  • Category set to API

Updated by Suma over 3 years ago

  • Private changed from Yes to No

Updated by Nou over 3 years ago

Just a reminder to people reading this as the source for documentation that the SQF call is actually...

"DllNameWithOutDotDll" callExtension "MyFunctionNameAndArgsAs_String_to_Parse_in_DLL"; // max length of funcs & arg being 4096 and same on the return value

Updated by Suma over 3 years ago

max length of funcs & arg being 4096 and same on the return value

Not really. The limit is for return value only. There is no limit on the input on the game side (the extension can impose some limits, but well implemented extension should handle arbitrary length input and at least fail gracefully).

Updated by Xeno over 3 years ago

Does work nicely with a managed DLL too (ofc unmanaged also).

Had some troubles making a callback into managed land (game crash), though it might be because I've called one DLL from two apps, one the game, the other one a C# app.
Both shared a callback pointer in a seperate segment of the dll (#pragma comment(linker, "/section:.someseg,RWS")) and the callback was calling some method in the C# app.

Updated by nomad_man over 3 years ago

Can we please get the dedicated linux support for that too?
Would love to have persistance/sql support, plus linux is working out a lot smoother for hosting.

Updated by Kenquinn over 3 years ago

Seconded having plugin support for Linux would be greatly appreciated.

Updated by oktane over 3 years ago

How is linux support supposed to work exactly? I suppose the DLL would have to not have any external MS references at all, which is a bit unheard of right? Or WINE/Mono would take care of that? I mean it's easy to request but can any linux experts think about the technical feasibility?

Regarding security, the command may be ideal with restrictions such as no directory transversal (can't load library outside of arma path, but subdirs okay so that it can be put in a modfolder and updated with mod managers like six updater if needed) and callextension is ignored if received from a network client? So that it cannot be used to craft something nasty and run remotely on people. (bugs may exist, buffer overflows, etc) Is that relevant or just paranoid?

Updated by nomad_man over 3 years ago

I'm no expert. But the dynamic (shared) library loads are nothing new in box windows and linux. Usually the search path is taken via environment variable or the configuration file.
Specifically i'm referring to LD_LIBRARY_PATH and ld.so.conf

It would be nice to have hooks into the game.

@oktane re security: are you referring to both implementations or only linux?

Updated by Nou over 3 years ago

Any chance we can get a basic call back function in to A2 through an event handler style interface? One of the big overheads in ACRE has been the streaming of data into C++ land instead of just calling for it when we need it. It'd be amazing to be able to "talk back".

Sort of unrelated, but giving us access to the UUID/GUID that you use for objects internally would also be amazing for "manipulating" objects in C++ land.

Updated by Suma over 3 years ago

A callback is possible, but it needs to be designed carefully. As the dll might be running its own threads, I am not willing to provide some kind of a "direct callback" which could be called anytime the dll wishes to, as this would make it too easy for badly designed dll to break the game. One design which I see as possible would be a scripted callback which would be valid only while dll is given control during the callExtension, and only from the thread which is executing the callExtension. However, I would need some example or more details on what you would like to achieve to be able to decide or design it.

UUID/GUID that you use for objects internally

I do not feel like giving the dll a direct access to our internal objects, that seems to unsafe to me. You should now expect to get more direct control than scripts currently have. (Sidenote: We are not using UUID/GUID for objects internally.)

Updated by Nou over 3 years ago

Yea a callback would def be a lot harder to manage... I'd have to think a bit as well on what exactly would be doable. Having direct access to the functions would be the nicest, though I am not sure how that would be done. I've never experimented with Fusion in VBS2 to know how well that works in their implementation.

On the note of UUID/GUID, some sort of way to access them (if they did) in SQF to pass to the DLL would be nice. Mainly so we could pass object identities around on our own network stack (in ACRE we use the TS3 network stack for a lot of stuff that needs to be more timely/heavy bandwidth) or for whatever other reason. Just some string representation of objects that can be looked up. I've debated trying to implement this myself via setVariable but the network overhead would be rather intense.

Updated by Suma over 3 years ago

On the note of UUID/GUID

I am a bit confused about the terminology. Are you talking about some kind of string id for scripting objects of type "Object" or "Group" only, or something identifying any internal C++ "object"? The first seems easy to me - each scripted "Object" or "Group" has a network id (a pair of integers), which would be easy to convert as a string an let you ask the object about it. If you want a reversed access as well (getting an object or a group from the ID), this would be possible as well. The interface could be:

netId object -> returning a string
netId group -> returning a string

objectFromNetId netIdString -> returning an object, if found, or objNull when not
groupFromNetId netIdString -> returning a group, if found, or grpNull when not

The pair of objectFromNetId / groupFromNetId seems necessary, as there is no polymorphism in the scripting available, therefore there is no way to get the access to the common ancestor of group/object in the script.

Updated by Nou over 3 years ago

Sorry, yes scripting objects, aka in game objects like people, tanks, fired rounds, anything that has a netId.

Updated by MaHuJa over 3 years ago

On the subject of callbacks, a variation of the model I was intending for a2u (which would be based on readfile) might work. Basically,

0 spawn {
  while (true) do {
    call compile "x" callExtension "callback";
    sleep 0.01;
  };
};

More importantly, how well will this work with linux servers? If no support for linux servers then this feature is basically useless for me, as I've committed to supporting linux with my creations. And depend on it for my own use as well.

Updated by MaHuJa over 3 years ago

oktane wrote:

How is linux support supposed to work exactly? I suppose the DLL would have to not have any external MS references at all, which is a bit unheard of right? Or WINE/Mono would take care of that? I mean it's easy to request but can any linux experts think about the technical feasibility?

Linux has .so where windows has .dll; conceptually they're the exact same thing - the catch is that the "shared object" has to be compiled specifically to run on linux. You can't just trivially convert a .dll to a .so and if the writer can't do portable code it's a bit more work getting it working on linux.

Regarding security, the command may be ideal with restrictions such as no directory transversal (can't load library outside of arma path, but subdirs okay so that it can be put in a modfolder and updated with mod managers like six updater if needed)

The plan seems to be that the search path for that dll/so is limited to the active mod folders. (I've said before, BIS are not clueless.) Even then it has to be a dll that does the desired work for the hacker in the "on load" part (attach, per process, per thread) or corresponding unload, or which exports the RVExtension function.

and callextension is ignored if received from a network client?

To my knowledge there is nothing that even tries to separate "local" and "network" originated script commands. This probably isn't doable without a full "taint tracking" system to begin with, which in itself would be exploitable (denial of service, just overwrite one of the variables the legit script uses). And be a hindrance to legitimate uses.

This is also the reason sql interfaces in sqf is a bad idea. "Anyone" can issue any (e.g. drop database) command. And with that I seem to have covered pretty much every database-using arma script other than bstats.

So that it cannot be used to craft something nasty and run remotely on people. (bugs may exist, buffer overflows, etc) Is that relevant or just paranoid?

That's highly relevant.

Executive summary for server managers and end users: Be very careful about accepting these modules. Once you put these inside your mod folders you're opening the door for sqf scripts to hack the server hosting it, rather than, as now, just crashing the game or causing "funny" effects in the game world. Scepticism is also far more deserved if they do not include the source code. (Jaylib has breached that barrier for a while now, but it's been the only one around.)

When amateurs write (native) code, refusing to be supported by their tools (and language), shit inevitably hits the fan. <rant> Universities usually train their students to do just that by teaching them "C with iostreams" rather than C++, and thus do all the resource management and buffer handling manually. In other words, if you're university trained in C++, I'll consider you an amateur until you prove otherwise. Show your source. ("C with Iostreams" is also known as "pre-standard C++" and "C++ as we used it in the 80s and 90s". Catch up a decade already.) </rant>

Presuming that you can do a script injection somehow, (unprotected server, you have a signing key the server accepts, network stream injection, all the other things we can't imagine) you can call that dll function with an arbitrary string. If it has a buffer overflow or other exploitable bug somewhere in how it handles that data, you're screwed.

The case of the malicious extension writer: Getting the sources from a reputable modder and compiling them yourself may be cumbersome, but it's far safer. He has a reputation on the line - backdoors will be discovered eventually - and he can't sneak anything "extra" into prebuilt dlls when you're compiling them yourself. Or you can just trust him - and take the fall if he turned out to be bad.

.....My response on a programming topic turned long again. Then again, I can't find other places this functionality is being specifically discussed.

Updated by kju over 3 years ago

  • Target version set to 1.61 BETA

Updated by kju over 3 years ago

BIKI article to be found here now thanks to MaHuJa‎:
http://community.bistudio.com/wiki/Extensions

Updated by Suma over 3 years ago

FYI: No linux support is planned at the moment.

Updated by Suma over 3 years ago

netId object -> returning a string
netId group -> returning a string

objectFromNetId netIdString -> returning an object, if found, or objNull when not
groupFromNetId netIdString -> returning a group, if found, or grpNull when not

Implemented in 90099

Updated by Nou over 3 years ago

I am in love with you Suma! <3

Thanks!

Updated by Dwarden over 3 years ago

in relation to possible Linux support - i was pointed by nix dedicated server owners to this page
http://www.openrce.org/blog/view/1761/DLL_Injection_on_Linux_using_Hotpatch

Updated by Gamma over 3 years ago

Dwarden wrote:

why not use v2 signature system to create bisign file for the .dll

that way it can be easily controlled by allowed .bikey on server
as DLL can be signed by author easily same as PBO

Any additional word on this?

The reason I ask is because I have working proof of concept, coded in c++, and as a very begginer on these programming topics, i'm a bit wary of the dll being made public (as i also intend to release the source) and eventually unleash some unintented hell (thinking of all of MaHuja's warnings). I could take inspiration from Scott's Arma2Net signed implementation, but I would prefer to keep my endeaviours in unmanaged land.

Afaik, only pbo's are checked against v2 signatures, and even if this is not a final solution, is there any news about checking also loaded dll's? Or one should take other types of cautions?

I am willing to let my source be reviewed before releasing it freely to public. Whoever offers, if any, to do this, keep in mind there is strong possibility of facepalming a lot at the a newbs code. I would humbly accomodate any criticism/suggestions to improve it, and would certainly appreciate pointers/references.

Updated by firefly2442 over 3 years ago

On the wiki, it says:

Extensions can not be used by serverside scripts. (Unless you can guarantee all instances it will run on be windows servers.)

Does this mean it will work on a normal full retail version of Arma2 as well as (only) the windows dedicated server versions?

http://community.bistudio.com/wiki/ArmA:_Dedicated_Server

Thanks.

Updated by Gamma over 3 years ago

If by Arma2 you actualy meant Arma: OA, the answer is affirmative, since Beta 87662 that the feature is available.

There is no intention to provide support in linux, though Dwarden appears to be in solution exploration mode.

Edit: Independently of linux support be possible or not, there should be a way for the mission creator to validate if the support for the dll is present or not.
So that if it is not present (mission was deployed in linux server) he can accomodate his script to that without spamming the rpt with sqf errors.
I did notice that if the actual dll is not found in betas that support callExtension no errors drop in the rpt, will linux server work the same...

Updated by MaHuJa over 3 years ago

On pre-87662 (like 1.60 non-beta) servers and clients, the compile part of loading the sqf will probably fail for any script that contains the callextension command.

I haven't actually tested windows servers, so I can't confirm or deny if it works on them. Presumably the code for making it work is independent of the client code, so I would assume it works. The problem is that if your addon (which extensions are part of) relies on it being available (on the server) then it will break for the majority of servers. (Last I checked, linux dedis dominated the server list.) If it's a pure client-side extension like acre, then you're in luck. If you're developing the extension for a specific server that you know will run windows (like some of the life rpgs, that used to rely on jaylib for db access) - it's also viable.

When it can't find the dll - or it's not supported - I believe callextension returns an empty string. (Working from memory here.)

Updated by nomad_man over 3 years ago

Dwarden, and others.

You can use custom memory allocators as i previously indicated using ld preload trick.
Here is a sample on how to use TCMalloc: http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html

Also, i'm working on a PoC for hijacking the rest of the calls. The previous link with hotpatching is how you can augment arma2 functionality. (e.g. arma2 sql extension)

Now, what i'm interested to see from other people is metrics on different allocators :)

Updated by Suma over 3 years ago

When it can't find the dll - or it's not supported - I believe callextension returns an empty string. (Working from memory here.)

Correct. This can be used to check for extension existence, if the extension is designed mindfully. See http://community.bistudio.com/wiki/Extensions#Extension_existence.2Fversion_checking

Updated by Nou over 3 years ago

Do the netId functions actually work? Just tried them and they don't seem to return anything?

Updated by Sickboy over 3 years ago

Nou wrote:

Do the netId functions actually work? Just tried them and they don't seem to return anything?

Tried from client or server, or both?

Updated by Nou over 3 years ago

Actually, this is going to sound stupid, but I'd assume they'd work in single player... :/ If thats not the case then we do need some solution to get objects in singleplayer from an ID... :(

Updated by Nou over 3 years ago

Anyway, the reason I ask for singleplayer is because I have a some what working C++ to SQF interface using callExtension, but its kind of hard to relate objects if there is no way to identify them. :(

Updated by Sickboy over 3 years ago

Rgr - interesting to know if it works at all in any machine type, or just not in SP.

Updated by MaHuJa over 3 years ago

In multiplayer sessions, netid gives a string in the general form of "1:2" - at least for any object that is global, like players. CreateVehicleLocal and map objects, probably not.
In singleplayer, netid gives an empty string for all objects.

I can see two options here;
a) A separate set of commands, e.g. objectid/getobjectfromid, which work in singleplayer as well as multiplayer, and isn't concerned about the values being transferrable to other clients in mp.
b) Making netid (and getfrom) use some other sort of reference for regular objects when in singleplayer. (What to do about non-net objects in mp...)

Updated by nomad_man over 3 years ago

nomad_man wrote:

Dwarden, and others.

You can use custom memory allocators as i previously indicated using ld preload trick.
Here is a sample on how to use TCMalloc: http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html

Also, i'm working on a PoC for hijacking the rest of the calls. The previous link with hotpatching is how you can augment arma2 functionality. (e.g. arma2 sql extension)

Now, what i'm interested to see from other people is metrics on different allocators :)

Here is my proof of concept how to hijack a system call. In this case getpid()


nomad@am:~/poc/pid$    cat > getpid.c
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>

    pid_t getpid(void)
    {
        printf("Hello, world!@42\n");
        //return syscall(SYS_getpid);
        return 42;
    }

nomad@am:~/poc/pid$   gcc -Wall -fPIC -shared -o getpid.so getpid.c

nomad@am:~/poc/pid$   LD_PRELOAD=./getpid.so bash -c 'echo $$'
Hello, world!@42
Hello, world!@42
42

Updated by kju about 3 years ago

Suma can you please consider to add a more usable signature for callExtension, like:

_return = extensionName<String> callExtension [functionName<string>,arguments<array>];
_result = ("Arma2Net.Unmanaged" callExtension ["WriteClipboardToFile",[_version,"supportInfo"]]);

Right now one has to convert variables to one long string which is not a nice design and error prone in SQF..

Updated by Suma about 3 years ago

Current form exactly matches how the arguments are passed to the extension. If the form you are requesting would be added, it would only merge the name and arguments into a single string anyway. I do not see any significant benefits in this - this can be done in a script the same way.

Updated by Suma about 3 years ago

  • Assignee changed from Suma to Dwarden

Updated by Nou about 3 years ago

I think kju was asking for the args to be passed to the external function in the same way too... I don't see any way to have that done easily though, as you'd need to handle conversion to things that don't have a native type in C and it'd get messy. I'd rather handle it myself, even if it is a bit cumbersome.

Updated by kju about 3 years ago

Pretext: I might not understand the system correctly - if so, please ignore.

Let me clarify:
  1. It should be rather simple to make a new sqf command called callExtensionArray for example which has: extensionName<String> callExtensionArray methodNameAndData<array> - with methodNameAndData containing: functionName<string>,arguments<array>
  2. The arguments could remain all of type String to avoid conversion issues
  3. However one could also allow simple datatypes like int, float, bool in addition to String (which is a char[]); sure there might be conversions issues, yet I assume the extension plugin/dll could handle that; right now we are only speaking of windows systems anyway; so there should not be too many target systems with different data handling

Right now I have as call:

_result = ("Arma2Net.Unmanaged" callExtension ("WriteClipboardToFile " + str([_versionText,"supportInfo"])));

and arma2net has to do this weird construct/conversion:

Format.SqfAsCollection(args, out arguments);
string version = arguments[0] as string;
string task = arguments[1] as string;

(source for SqfAsCollection)

Could it be done better on the arma2net side - I cannot tell.
However to me to have a "collection" (array) rather than a string with some separators and quotes in quotes (in quotes, etc) handling, seems a better design.

But as said I might be completely off too.

Updated by Nou about 3 years ago

That should be something Arma2Net decides how to handle, not BIS in my opinion. There is nothing stopping Arma2Net from providing more robust user functions for sending messages in SQF. Also leaving the string arg delimiters in the hands of the coders of the plugin I think is far more useful than BIS choosing one to use.

Updated by kju about 3 years ago

  1. I said as an addition - NOT change the current signature Nou. Please read more closely.
  2. A long string vs an array or string or simple data types is nothing the plugin/interface developer can influence.

Updated by MaHuJa about 3 years ago

Right now one has to convert variables to one long string which is not a nice design and error prone in SQF..

How about making a sqf function, calla2net, with the signature
yourArraySpecAbove call calla2net;
where that conversion is handled once and for all? Which could then be loaded and compiled by the a2net addon (which is needed to have the dll in the first place, after all).

I might not understand the system correctly

I'll try help you along. I believe the reasons for the single string has everything to do with

1) API simplicity. Look at how even the BIS provided code examples screwed up with an off-by-one crash bug. Add multiple strings, an array of pointers to those strings (requiring double dereferences to get at the string itself, deallocating it afterwards) and you have plenty more opportunities for bugs. That stuff isn't trivial either, so you'd raise the bar for making extensions to those quite proficient in C bit shuffling - that is probably why it wasn't done in the first place.

2) ABI compatibility.

The abi compatibility of a single char* is the last thing that'll fail.

> one could also allow simple datatypes like int, float, bool in addition to String (which is a char[]); sure there might be conversions issues, yet I assume the extension plugin/dll could handle that;

No it can't. We're talking C interfaces here. If it expects a char* and you pass it a (int) 1, it will try to access that memory address, and crash. (segfault on *nix, access violation on windows) And then there's all the fun that can be had by carefully selecting your number...
Basically, if you pass a different set of value types than the program is expecting, the program has no way of detecting what type it was passed. We usually solve this by detecting such mismatches at compile time, but this isn't possible when parameter types are not determined until runtime.
(The program could pass along metadata specifying the type of the variable. This would seriously complicate the C API though.)

Basically, to have this wish, arma2 would have to become .net aware specifically for a2net. In which case you'd essentially be asking for a calla2net function.

And even if they went that far, you'd really only be getting rid of the Format.SqfAsCollection(args, out arguments); line. That's a single line of boilerplate.

To get rid of all of it, such that you could simply write args["version"] or similar to access it instead of declaring it as a separate string, would be possible; but would also require explicit naming of the variables on the call site. Plus everything in between will be a mess, unless you do it by formatting it all to a string (sqf) and parse it into a map/dictionary on the a2net side. Using the current callextension interface. The sqf functions to do that would ideally be written, extensively tested, and never changed again. Certainly not rewritten by every user.

Any questions?

Updated by kju about 3 years ago

  • Target version changed from 1.61 BETA to 1.63 BETA

Updated by th3flyboy about 3 years ago

Based on my comments in the Thinktank:
It would be ideal to add linux support by having C++ extension DLLs compiled using MinGW rather than visual studio. The documentation here explains how to call MinGW DLLS in VS and G++:

http://www.mingw.org/wiki/MSVC_and_MinGW_DLLs
http://stackoverflow.com/questions/1291594/using-libs-dlls-compiled-in-linux-mingw-in-visual-studio
http://stackoverflow.com/questions/9611419/using-dlls-compiled-with-mingw-gcc-with-visual-c-project
http://www.mingw.org/wiki/sampleDLL

Note however: You can not use MSVS compiled DLLs on the Linux server, that is where you open a nasty can of worms.

Updated by Gamma about 3 years ago

slightly related to th3flyboy comment, to interest of those compiling in mingw:

Advanced MingW DLL topics

Exporting Undecorated stdcall Functions
If you are exporting functions from a DLL and you’re using the stdcall calling convention, you’ll find that MinGW decorates the functions exported from the DLL. For example if you have a function with the signature “int Add(int, int)”, the exported name will be “Add@8”. The linker has added an ‘@’ sign after the function name, followed by the size of the function arguments in >bytes. However, if you’re using Microsoft’s Visual C++ you’ll find that it additionally prefixes the name with an underscore, for example “_Add@8”.

Because of this in my mingw compiled dlls, i find it easier to adapt the code to:

extern "C" 
{
  __declspec(dllexport) void __stdcall _RVExtension(char *output, int outputSize, const char *function); // note the underscore in "_RVExtension" 
};

Disclaimer: not exacly a programmer here, but aside of code portability issues i am unable to see any side effects of this.

Updated by MadStyleCow almost 3 years ago

Hello,

Could any one provide a VS sample project?

Updated by SGTGunner over 2 years ago

Is there any update to this specifically around linux support and or MinGW templates or examples?

Thanks in Advance.

Updated by firefly2442 over 1 year ago

Quotes from Dwarden indicate callExtension support is currently in testing/development for Linux servers.

SGTGunner wrote:

Is there any update to this specifically around linux support and or MinGW templates or examples?

Thanks in Advance.

Updated by firefly2442 over 1 year ago

Arma3 1.18 was just released and lists callExtension support in Linux in the changelog.

http://dev.arma3.com/spotrep-00024

firefly2442 wrote:

Quotes from Dwarden indicate callExtension support is currently in testing/development for Linux servers.

SGTGunner wrote:

Is there any update to this specifically around linux support and or MinGW templates or examples?

Thanks in Advance.

Also available in: Atom PDF