ID:2359294
 
Code:
call("./shell_output.so","shell")(command_args)

Runtime Error
runtime error: Unable to load library shell_output.so


Problem description:
I tried several things, spent the afternoon and the night trying different things. Different forms of compiling, different folders, different files (including the F1 help example) and more.

Is there anything missing to install on my machine? I can host normally. Yes, I'm using -trusted.

The only .so file that I get a different response from is libbyond.so. In all other attempts it is the same error.

runtime error: /usr/local/lib/libbyond.so: undefined symbol: helpMePlease
Your .so file should be located in ~/.byond/bin -- that includes for root installs. You also need to be sure it's compiled 32-bit.

What output do you get when you use
file shell_output.so


and

ldd shell_output.so


?
In response to Nadrew
I would like to point out that I am a beginner on this subject. But I need to use that.

Source (original)
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>

std::string exec(const char* cmd) {
char buffer[128];
std::string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
} catch (...) {
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}

Compile command:
apt-get install g++:i386   
g++ -m32 -fPIC -shared neo.cpp -o matrix.so


file matrix.so
matrix.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=89312a58d968cbab778da1f61902aaefec014503, not stripped


nm -gC matrix.so
00003064 B __bss_start
U __cxa_allocate_exception@@CXXABI_1.3 U __cxa_atexit@@GLIBC_2.1.3
U __cxa_begin_catch@@CXXABI_1.3 U __cxa_end_catch@@CXXABI_1.3 w __cxa_finalize@@GLIBC_2.1.3
U __cxa_free_exception@@CXXABI_1.3 U __cxa_rethrow@@CXXABI_1.3 U __cxa_throw@@CXXABI_1.3
00003064 D _edata
00003068 B _end
U feof@@GLIBC_2.0
U fgets@@GLIBC_2.0
00000ed4 T _fini
w __gmon_start__
U __gxx_personality_v0@@CXXABI_1.3 00000914 T _init w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
U pclose@@GLIBC_2.1
U popen@@GLIBC_2.1 U __stack_chk_fail@@GLIBC_2.4 U _Unwind_Resume@@GCC_3.0
00000bd0 T exec[abi:cxx11](char const*)
U std::allocator<char>::allocator()@@GLIBCXX_3.4 U std::allocator<char>::~allocator()@@GLIBCXX_3.4 U std::runtime_error::runtime_error(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@GLIBCXX_3.4.21
U std::runtime_error::~runtime_error()@@GLIBCXX_3.4 U std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)@@GLIBCXX_3.4.21 U std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@@GLIBCXX_3.4.21
U std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char const*)@@GLIBCXX_3.4.21 U std::ios_base::Init::Init()@@GLIBCXX_3.4 U std::ios_base::Init::~Init()@@GLIBCXX_3.4
U typeinfo for std::runtime_error@@GLIBCXX_3.4


ldd matrix.so
        linux-gate.so.1 =>  (0xf7fc7000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xf7e3f000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf7e22000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7c6c000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7c17000)
/lib/ld-linux.so.2 (0xf7fc9000)
Looks good on the file itself, you may need to set LD_LIBRARY_PATH to the same path as your .so file before starting your dmb.
In response to Nadrew
I can connect with the .so file now, but I don't know what symbol use and if have some problem with the code.


runtime error: ./matrix.so: undefined symbol: exec

You don't have it exported properly, nor are you using the correct arguments for a call() to the DLL.

extern "C" __attribute__((visibility("default"))) std::string exec(int argc, char *args[])


argc is the number of arguments passed to the function, args[] is the array of chars containing the values passed.

If you want to cross compile on Windows/Linux easily you can use a macro like

#if defined(_MSC_VER)
// Windows
#define EXPORT __declspec(dllexport)
#define IMPORT __declspec(dllimport)

#elif defined(__GNUC__)
// GCC/G++
#define EXPORT __attribute__((visibility("default")))
#define IMPORT
#else
// Do nothing and hope for the best?
#define EXPORT
#define IMPORT
#pragma warning Unknown OS, linking may be touchy
#endif


and use EXPORT orIMPORT in place of the __attribute() or __declspec() calls.
Did I do something wrong?

runtime error: ./matrix.so: undefined symbol: exec


#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>

extern "C" __attribute__((visibility("default"))) std::string exec(int argc, char *args[]);

std::string exec(const char* cmd) {
char buffer[128];
std::string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
} catch (...) {
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
That was meant to replace your definition of exec(), not go next to it. exec() as it is does not get exported into the library, you need the extern "C" bit BEFORE the function's type and name. (and you can't use a single const char as an argument).

You CAN define an exported function that calls exec(), but that's basically redundant here.
In response to Nadrew
working now, thank you so much.
Unfortunately it uses 98% cpu for a fraction of a second giving a fast freeze to everyone, I go to sleep, when I wake up I see what I can do.
call() is a blocking function, it will wait for your C++ function to return before continuing, if you'd probably want to spawn() off the call (or use it inside of a proc with waitfor = 0) so the game can continue while the shell command executes.
In response to Nadrew
I tried some things, some of them below, and none had any different behavior.

proc/_shellNotReturn(command_args)
spawn(0) call("./[libsaraiva]","exec")(command_args)


proc/_shellNotReturn(command_args)
set waitfor = 0
sleep()
call("./[libsaraiva]","exec")(command_args)


proc/_shellNotReturn(command_args)
set waitfor = FALSE
sleep()
call("./[libsaraiva]","exec")(command_args)


proc/_shellNotReturn(command_args)
set waitfor = FALSE
spawn call("./[libsaraiva]","exec")(command_args)
I found a alternative solution.

const char * exec(int argc, char ** argv) {
popen(argv[0], "r");
}
If you don't need the results of the command, you can use system(), which is going to be faster.

You only need popen() if you need the results of the command, and since your code isn't using that anyways it's better to use system().