unos baghaii
unos baghaii

Reputation: 2679

Cross platform c++ integrated with c# in Linux and Windows

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.

Upvotes: 3

Views: 1148

Answers (1)

CristiFati
CristiFati

Reputation: 41116

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:

Upvotes: 3

Related Questions