Timo17 2 Posted July 13, 2016 Hello, I have problems making an extension in C for Arma in Linux (Ubuntu 16.04). For testing I just took the example from the wiki : #include <string.h> // strcmp, strncpy static char version[] = "1.0"; void RVExtension(char *output, int outputSize, const char *function) { if (!strcmp(function, "version")) { strncpy(output, version, outputSize); } else { strncpy(output, function, outputSize); } output[outputSize-1]='\0'; return; } After creating the .c file I use the command "gcc -shared -fPIC -o example.so example.c" without any errors. I place example.so in the root folder of my arma 3 server. I start the server but infortunately I have no confimation of the loading of the extension in the logs and in the game if i launch : "hint ("example" callExtension "version");" nothing happen. I hope someone can help me with this. Thanks in advance. Share this post Link to post Share on other sites
pedeathtrian 100 Posted July 13, 2016 My first guess is you're using amd64 architecture, so abovementioned command creates x86-64 binary, whereas arma3server is 32-bit. Try gcc -shared -fPIC -m32 -o example.so example.c UPD. This step may give you linker error, something like: /usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc.a when searching for -lgcc /usr/bin/ld: cannot find -lgcc /usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.9/libgcc_s.so when searching for -lgcc_s /usr/bin/ld: cannot find -lgcc_s collect2: error: ld returned 1 exit status In this case install the package containing these files for 32bit architecture, most likely could be found with command apt-file search 32/libgcc.a (lib32gcc-4.9-dev in my case) 1 Share this post Link to post Share on other sites
Timo17 2 Posted July 13, 2016 Thanks for the reply, the command you gave work perfectly but this is not working in the game and always no clue in the logs. I have done a ldd command ldd example.so Here the output : linux-gate.so.1 => (0xb7759000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb757e000) /lib/ld-linux.so.2 (0xb775a000) Share this post Link to post Share on other sites
Timo17 2 Posted July 13, 2016 I also run that command to check if it's actually loaded or not lsof -p ... and like I was thinking it's not. Share this post Link to post Share on other sites
pedeathtrian 100 Posted July 14, 2016 After some strace'ing I found that arma3server tries to open extension in that order: 1. In directories of all mods passed in command line (in reverse order), e.g. "/path/to/Steam/SteamApps/common/Arma 3 Server/mods/@allinarmaterrainpack/example.so" 2. In root directory, i.e. "/example.so" 3. In directories of stock addons installed, e.g. "/path/to/Steam/SteamApps/common/Arma 3 Server/{mark,heli,kart,curator}/example.so" 4. In root directory again. (why?) 5. In current working directory, that is "./example.so" This order does not look like standard procedure for locating shared objects, so I guess having arma3server with RPATH set or not set to $ORIGIN does not make too much difference (and it is set anyway). Therefore I think it is not enough to just place the .so in the same directory as server executable. Make sure you also set cwd to that directory before launching server. Extension is loaded on first use: file is opened, mmap'ed, then descriptor closed; that keeps file in process' list of open files (lsof); unmmap'ed on process exit. So I had extension loaded, NO confirmation of that appeared in server logs, therefore I suggest adding some debug messages into extension's code: /* * example.c * * gcc -shared -fPIC -m32 -o example.so example.c */ #include <string.h> // strcmp, strncpy #include <stdio.h> // fprintf static char version[] = "1.0"; void RVExtension(char *output, int outputSize, const char *function) { fprintf(stderr, "%s:%d: RVExtension: output: %p; outputSize: %d; function: \"%s\".\n", __FILE__, __LINE__, output, outputSize, function); if (!strcmp(function, "version")) { strncpy(output, version, outputSize); } else { strncpy(output, function, outputSize); } output[outputSize-1]='\0'; return; } I have these lines in mission's init.sqf: ext_result = "example" callExtension "version"; diag_log format ["ext_result = ""example"" callExtension ""version""; ext_result == ""%1""", ext_result]; And I have this output in server log: example.c:13: RVExtension: output: 0xfff166e0; outputSize: 10240; function: "version". 17:01:24 "ext_result = "example" callExtension "version"; ext_result == "1.0"" Further checking, I run this command from client's debug console while in-game: ["example", "foo"] remoteExec ["callExtension", 2] Extension works only sever-side, therefore remoteExec with targets = 2. That causes following output: example.c:13: RVExtension: output: 0xfffba6b0; outputSize: 10240; function: "foo". Finally, when I stop the server, last lines I see are as follows: 18:16:57 Extensions: 18:16:57 example (./example.so) [] [] Seems like everything works as expected (except confirmation of load). Tested on 1.54 legacy port server (for 1.54 legacy port clients), but I don't think things are broken in actual version. 1 Share this post Link to post Share on other sites
Timo17 2 Posted July 14, 2016 Thank you a lot for your thorough research that resolved my problem. I'm very grateful. but I don't think things are broken in actual version. You've right, It's working in 1.62. Share this post Link to post Share on other sites