ID:156824
 
So, there's some C code I am trying to make into a .so (shared library) file. It's mentioned in the DM Help that an .so file is what's needed on a unix machine.
I am accessing the dll using the call() proc.

The main reason I am trying .so, is because my .dll didn't work on the Unix machine. But, even though I tried to make a .so, it still gives me "runtime error: Unable to load library nature.so". I am completely sure I am loading the game in Trusted Mode.

I am accessing the Unix machine over a network through the internet. I am not sure if the probelm is because it is over the internet, or because I did not compile the .so file correctly.

The C code is as follows:
#include <stdio.h>
#include <stdlib.h>

extern char *nature(int argc, char **argv)
{
static char text[3] = "1";

if (argc == 2)
{
static unsigned int pv1, pv2, nature;

pv1 = (unsigned int) atoi(argv[0]);
pv2 = (unsigned int) atoi(argv[1]);
nature = (pv1 | (pv2 << 16U)) % 25U + 1U;

sprintf(text, "%u", nature);
}
else
fprintf(stderr, "Wrong number of arguments for nature function!\n");

return text;

}


I compiled it using the following command lines:
gcc -c -fpic nature.c
gcc -shared -lc -o nature.so nature.o

Am I compiling it right? What could be wrong?
I imagine LummoxJR might know what's wrong?
Where are you putting the shared object, and what world security are you running at?

Edit: I'm having a few issues myself, and I'm fairly sure it's not your code.
In response to Stephen001
The .so file is being put into the same folder with the .dmb and .rsc. I didn't have trouble getting a .dll to work on a Windows machine.
Also, I am running it in trusted mode.
I'm having the same issue: BYOND informs me that it can't read the .so file even though it's in the same folder as the .dmb and it's running in trusted mode.
Right. I'm using the sample code provided in the reference.

The C++ code:
#include <string.h>

#ifdef WIN32
#define EXPORTED __declspec(dllexport)
#else
#define EXPORTED
#endif

extern "C" EXPORTED char *merge(int n, char *v[]){
static char buf[500];
*buf=0;
for(int i=0;i<n;i++) {
strcat(buf,v[i]); // we should bounds-check but it's a stupid example!
}
return buf;
}


Test BYOND Project:
mob
verb
merge_text()
var/dll = world.system_type == MS_WINDOWS ? "merge.dll" : "merge.so"
src << "Calling [dll]:merge(\"hello\", \"world\")"
src << "Result: [call(dll, "merge")("hello", "world")]"
Login()
src << "Welcome back, [key]."


On Windows, I'm using Visual C++ 2008 to compile it. On Linux, I'm using the GNU compiler (g++) with the following instructions:
g++ -c -fpic merge.cc -o merge.o
g++ -shared -lc -o merge.so merge.o


Output when executing the code on Windows:
Welcome back, Android Data.
Calling merge.dll:merge("hello", "world")
Result: helloworld


Output when executing the same code on Linux:
Welcome back, Android Data.
Calling merge.so:merge("hello", "world")
runtime error: Unable to load library merge.so
proc name: merge text (/mob/verb/merge_text)
source file: mobs.dm,6
usr: Android Data (/mob)
src: Android Data (/mob)
call stack:
Android Data (/mob): merge text()


I can confirm that merge.so is in the same folder as the .dmb and that the appropriate permissions are set. And yet, it claims to be unable to load the exact same library I loaded just fine on Windows.

Am I doing something wrong? Is this a BYOND Bug?

EDIT: Tried it with a C application too. Works fine on Windows, but Linux fails.

#include <string.h>
//#include <lua.h>


#ifdef WIN32
#define EXPORTED __declspec(dllexport)
#else
#define EXPORTED
#endif

extern EXPORTED char *merge(int n, char *v[]){
static char buf[500];
int i = 0;

*buf = 0;
for(i = 0; i < n; i++){
strcat(buf,v[i]); // we should bounds-check but it's a stupid example!
}
return buf;
}


gcc -c -fpic merge.c -o merge.o
gcc -shared -lc -o merge.dll merge.o
rm /home/adrift/adrift/merge.dll
cp merge.dll /home/adrift/adrift/


Test BYOND Project:
mob
verb
merge_text()
var/dll = "merge.dll"
src << "Calling [dll]:merge(\"hello\", \"world\")"
src << "Result: [call(dll, "merge")("hello", "world")]"
Login()
src << "Welcome back, [key]."
In response to Android Data
BYOND uses dlopen() on unix to open the shared library.

"The function dlopen() loads the dynamic library file named by the null-terminated string filename and returns an opaque "handle" for the dynamic library. If filename is NULL, then the returned handle is for the main program. If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details):

- (ELF only) If the executable file for the calling program contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, then the directories listed in the DT_RPATH tag are searched.

- If the environment variable LD_LIBRARY_PATH is defined to contain a colon-separated list of directories, then these are searched. (As a security measure this variable is ignored for set-user-ID and set-group-ID programs.)

- (ELF only) If the executable file for the calling program contains a DT_RUNPATH tag, then the directories listed in that tag are searched.

- The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is checked to see whether it contains an entry for filename.

- The directories /lib and /usr/lib are searched (in that order)."


In short, try this:
var/dll = world.system_type == MS_WINDOWS ? "merge.dll" : "./merge.so"
In response to Slurm
I got it working. Thanks!