2

I have the following code in c++ to determine available RAM in os

#if defined(_WIN32)
#include <stdio.h>
#include <windows.h>
#include "string.h"
#include "setjmp.h"
#elif defined(__linux__)
#include "stdio.h"
#include "string.h"
#include <unistd.h>
#endif

extern "C"
{
    unsigned long long getAvailableSystemMemory_Windows64();
    unsigned long long getAvailableSystemMemory_Linux64();
}

#if defined(_WIN32)

__declspec(dllexport) extern unsigned long long getAvailableSystemMemory_Windows64()
{

MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullAvailPhys / 1024 / 1024;
}

#elif defined(__linux__)

extern unsigned long long getAvailableSystemMemory_Linux64()
{

unsigned long long ps = sysconf(_SC_PAGESIZE);
unsigned long long pn = sysconf(_SC_AVPHYS_PAGES);
unsigned long long availMem = ps * pn;
return availMem / 1024 / 1024;
}

#endif

int main()
{
#if defined(_WIN32)
    printf("%d", getAvailableSystemMemory_Windows64());
#elif defined(__linux__)
    printf("%d", getAvailableSystemMemory_Linux64());

#endif
printf("MB");

int a;
scanf("This is the value %d", &a);
}

and the following code in c#

class Program
{

    [DllImport("hello.dll", CallingConvention = CallingConvention.Cdecl)]
    extern static long getAvailableSystemMemory_Windows64();


    [DllImport("hello.so", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "getAvailableSystemMemory_Linux64")]
    extern static long getAvailableSystemMemory_Linux64();

    static void Main(string[] args)
    {
        long text = 0;
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            text = getAvailableSystemMemory_Windows64();
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            text = getAvailableSystemMemory_Linux64();


        Console.WriteLine(text);
        Console.WriteLine("Hello World!");
        Console.ReadLine();
    }

}

Then in windows I compile c++ code using g++ --shared -o hello.dll hello.cpp and copy the dll to debug folder. everything is ok.

for Linux I compile it on Opensuse using g++ -o hello.so hello.cpp and copy the .so file into the debug but it doesn't work. I get the exception

Unhandled Exception: System.DllNotFoundException: Unable to load shared 
library 'hello.so' or one of its dependencies. In order to help diagnose 
loading problems, consider setting the LD_DEBUG environment variable: 
libhello.so.so: cannot dynamically load executable
at CallCDll.Program.getAvailableSystemMemory_Linux64()
at CallCDll.Program.Main(String[] args) in 
/home/CallCDll/Program.cs:line 22

I added the .so file dir path to LD_LIBRARY_PATH using LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/CallCDll/bin/Debug/netcoreapp2.2 but doesn't work.

What Should I do? Wherever I copy the .so file, it cannot find it.

unos baghaii
  • 2,539
  • 4
  • 25
  • 42
  • I'm not much of a Linux man myself but, from the error message it seems you shouldn't include the `.so` part in your `DllImport` line - system is looking for `hello.so.so` (.so: good they added it twice - hehe). – Adrian Mole Sep 02 '19 at 11:59
  • @Adrian now I get `Unhandled Exception: System.DllNotFoundException: Unable to load shared library 'hello' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libhello: cannot open shared object file: No such file or directory at CallCDll.Program.getAvailableSystemMemory_Linux64() at CallCDll.Program.Main(String[] args) in /home/CallCDll/Program.cs:line 22 ` – unos baghaii Sep 02 '19 at 12:03
  • Damned if you do, damned if you don't! Like I said, I'm not really a Linux man. But why also is it looking for "libhello" rather than "hello?" Have you tried simply renaming your `hello.so` to `libhello.so.so` ?? – Adrian Mole Sep 02 '19 at 12:06
  • Did you declare your C++ function as `extern "C"` to prevent the compiler from mangling it? – Botje Sep 02 '19 at 12:08
  • @Adrian I don't know too – unos baghaii Sep 02 '19 at 12:09
  • @Botje Yes, I have added – unos baghaii Sep 02 '19 at 12:10
  • There are certainly better ways to check for available system memory than using extern DLLs – nada Sep 02 '19 at 13:19
  • The shared object should be called libhello.so. Try `g++ -o libhello.so hello.cpp`. https://www.tecmint.com/understanding-shared-libraries-in-l – Thomas Sablik Sep 02 '19 at 14:36
  • Why is the **`-shared`** flag missing from the *Lnx* command? Note that it would also imply **`-fPIC`**. Also, not sure why *func*s are *extern*. – CristiFati Sep 03 '19 at 06:06
  • @CristiFati Thanks man. It worked . `g++ -o libhello.so hello.cpp --shared -fPIC ` I used this. – unos baghaii Sep 03 '19 at 06:18
  • @unosbaghaii: :) One more question: Does it still work if you name the lib *hello.so* (`-o hello.so`)? Assuming that the *C#* code is unchanged: `[DllImport("hello.so", ...`. According to the error message you got, it should work as that's the library that's being attempted to load. – CristiFati Sep 03 '19 at 06:31
  • @CristiFati in c# is `[DllImport("hello.so", ...`. it works with both `-o hello.so` and `-o libhello.so` in debug folder. Apparently it searches for both names – unos baghaii Sep 03 '19 at 06:39
  • @unosbaghaii: It's what I expected. But when building *libhello.so* did you delete *hello.so* before running your program? – CristiFati Sep 03 '19 at 06:41
  • Here's some interesting approach https://www.codeproject.com/Tips/709270/Csharp-NET-Interoperability-with-Native-C-Librarie – 0dminnimda Jun 09 '22 at 08:37

1 Answers1

3

According to [Man7]: GCC(1) (man gcc):

-shared

Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option. For predictable results, you must also specify the same set of options used for compilation (-fpic, -fPIC, or model suboptions) when you specify this linker option.[1]

So, your command didn't generate a shared object or library (.so), but an executable (even if named hello.so). If you try running it, you'll see the output from main.
To fix things, change your build command to:

g++ -shared -fPIC -o hello.so hello.cpp

Other notes:

CristiFati
  • 38,250
  • 9
  • 50
  • 87